@blurt-blockchain/blurt-mcp-server 0.4.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/LICENSE +682 -0
  3. package/README.md +117 -0
  4. package/SECURITY.md +107 -0
  5. package/dist/app.js +88 -0
  6. package/dist/buildServer.js +146 -0
  7. package/dist/contracts/registerBlurtTool.js +53 -0
  8. package/dist/contracts/toolRegistry.js +384 -0
  9. package/dist/resources/blurtResource.js +82 -0
  10. package/dist/server-stdio.js +37 -0
  11. package/dist/server.js +35 -0
  12. package/dist/tools/claimRewards.js +48 -0
  13. package/dist/tools/comment.js +58 -0
  14. package/dist/tools/compareAccounts.js +50 -0
  15. package/dist/tools/fetch.js +91 -0
  16. package/dist/tools/follow.js +39 -0
  17. package/dist/tools/getAccount.js +80 -0
  18. package/dist/tools/getAccountHistory.js +109 -0
  19. package/dist/tools/getAccountNotifications.js +40 -0
  20. package/dist/tools/getAccountPosts.js +130 -0
  21. package/dist/tools/getAccountRelationships.js +34 -0
  22. package/dist/tools/getAccountSubscriptions.js +50 -0
  23. package/dist/tools/getAccountWitnessVotes.js +46 -0
  24. package/dist/tools/getBlurtPrice.js +43 -0
  25. package/dist/tools/getChainStatus.js +94 -0
  26. package/dist/tools/getCommunity.js +75 -0
  27. package/dist/tools/getDelegations.js +37 -0
  28. package/dist/tools/getPendingRewards.js +53 -0
  29. package/dist/tools/getPost.js +88 -0
  30. package/dist/tools/getPostReblogs.js +29 -0
  31. package/dist/tools/getPostVotes.js +78 -0
  32. package/dist/tools/getPublications.js +109 -0
  33. package/dist/tools/getReferrals.js +39 -0
  34. package/dist/tools/getVoteValue.js +67 -0
  35. package/dist/tools/getWitness.js +46 -0
  36. package/dist/tools/listCommunities.js +90 -0
  37. package/dist/tools/listWitnesses.js +48 -0
  38. package/dist/tools/lookupAccounts.js +30 -0
  39. package/dist/tools/mute.js +39 -0
  40. package/dist/tools/post.js +42 -0
  41. package/dist/tools/readNotifications.js +35 -0
  42. package/dist/tools/reblog.js +39 -0
  43. package/dist/tools/search.js +189 -0
  44. package/dist/tools/subscribeCommunity.js +39 -0
  45. package/dist/tools/upvote.js +48 -0
  46. package/dist/utils/blurtUri.js +61 -0
  47. package/dist/utils/loadEnv.js +21 -0
  48. package/dist/utils/logger.js +63 -0
  49. package/dist/utils/price.js +21 -0
  50. package/dist/utils/rpc.js +126 -0
  51. package/dist/utils/signer.js +350 -0
  52. package/docs/adr/0001-neutral-infrastructure.md +50 -0
  53. package/docs/architecture.md +62 -0
  54. package/docs/cache-policy.md +42 -0
  55. package/docs/clients.md +78 -0
  56. package/docs/deployment.md +102 -0
  57. package/docs/development.md +51 -0
  58. package/docs/install-snippets.md +236 -0
  59. package/docs/load-testing.md +51 -0
  60. package/docs/operations.md +56 -0
  61. package/docs/release-provenance.md +63 -0
  62. package/docs/tools.generated.md +89 -0
  63. package/docs/tools.md +102 -0
  64. package/docs/usage.md +157 -0
  65. package/docs/write-operations.md +223 -0
  66. package/package.json +77 -0
package/docs/tools.md ADDED
@@ -0,0 +1,102 @@
1
+ # Tools & resources
2
+
3
+ The server exposes **25 read-only tools** (always available) plus **opt-in write tools** (local stdio
4
+ by default; HTTP signing requires an explicit unsafe trusted-deployment override — see
5
+ [write operations](./write-operations.md)).
6
+
7
+ ## Tools
8
+
9
+ | Tool | Description |
10
+ | --- | --- |
11
+ | `get-account` | Full account info: profile, wallet balances, Blurt Power, delegations, witness votes, rewards. |
12
+ | `get-account-history` | Account operation history, optionally filtered by operation type (vote, transfer, comment, …). |
13
+ | `get-account-posts` | Posts related to an account (blog, feed, posts, comments, replies, payout) via the Nexus L2 API. |
14
+ | `get-post` | A single post, or the full discussion tree (`with_comments=true`). |
15
+ | `get-publications` | Ranked posts (trending, hot, created, promoted, payout, …) via Nexus `getRankedPosts`. |
16
+ | `get-blurt-price` | Current BLURT price in USD and BTC from the public price feed. |
17
+ | `get-chain-status` | Network + market overview: head block, supply, reward fund, participation, price, market cap. |
18
+ | `list-communities` | Directory of Blurt communities (rank / new / subscribers), with search and pagination. |
19
+ | `get-community` | Details of a single community (subscribers, moderators, pending payout, …). |
20
+ | `get-post-votes` | Votes on a post/comment ranked by weight (rshares), for curation analysis. |
21
+ | `get-vote-value` | Estimated value of an account's upvote, in BLURT and USD, at a given weight. |
22
+ | `list-witnesses` | Top witnesses (block producers) ranked by vote weight, with missed blocks and version. |
23
+ | `get-witness` | Single witness details + a health read (vote weight, blocks behind head, enabled). |
24
+ | `get-account-witness-votes` | Which witnesses an account supports (and its proxy, if any). |
25
+ | `get-account-relationships` | Follower/following counts and a sample of each (social graph). |
26
+ | `get-pending-rewards` | Unclaimed author/curation rewards (claimable now), in BLURT and USD. |
27
+ | `get-account-subscriptions` | Communities an account is subscribed to, with its role in each. |
28
+ | `compare-accounts` | Side-by-side metrics for 2–5 accounts (BP, reach, output, earnings) in one call. |
29
+ | `get-referrals` | Accounts a referrer brought to Blurt (beBlurt referral system), with the total count. |
30
+ | `get-account-notifications` | An account's recent notifications (mentions, replies, votes, follows, reblogs) + unread count. |
31
+ | `get-post-reblogs` | The accounts that reblogged a post, and how many (reach signal beyond votes). |
32
+ | `get-delegations` | Outgoing Blurt Power delegations of an account (per delegatee), converted to BLURT. |
33
+ | `lookup-accounts` | Autocomplete Blurt account names by prefix (alphabetical). |
34
+ | `search` | Resolve a free-form query into Blurt resource links (account, history, posts, single post). |
35
+ | `fetch` | Retrieve the raw JSON of a Blurt resource from a `blurt://…` URI or shorthand id. |
36
+
37
+ `search` and `fetch` follow the connector convention used by ChatGPT-style clients.
38
+
39
+ Each tool ships with a verbose, LLM-oriented description (visible in the client) explaining when to
40
+ use it, its parameters and its output — for an AI client, the description *is* the interface.
41
+
42
+ The v1-candidate contract index is generated from source-of-truth registry metadata in
43
+ [`tools.generated.md`](./tools.generated.md). Regenerate it with `npm run docs:tools` and verify it
44
+ with `npm run docs:check`.
45
+
46
+ ## Write tools (opt-in, local stdio by default)
47
+
48
+ | Tool | Description |
49
+ | --- | --- |
50
+ | `blurt-claim-rewards` | Claim the configured account's pending rewards (`claim_reward_balance`). Supports `dry_run`. |
51
+ | `blurt-upvote` | Upvote a post/comment as the configured account (`vote`), at a given weight. Supports `dry_run`. |
52
+ | `blurt-comment` | Reply to a post/comment as the configured account (`comment`). Stamps `json_metadata.app = blurt-mcp/<version>` and appends a `via Blurt-MCP` footer. Supports `dry_run`. |
53
+ | `blurt-post` | Publish a new top-level post (title, body, tags). Same `blurt-mcp` app stamp + footer as `blurt-comment`. Supports `dry_run`. |
54
+ | `blurt-follow` | Follow or unfollow an account (`custom_json` follow). Supports `dry_run`. |
55
+ | `blurt-mute` | Mute (ignore) or unmute an account (`custom_json` follow/ignore). Supports `dry_run`. |
56
+ | `blurt-subscribe-community` | Subscribe to or leave a community (`custom_json` community). Supports `dry_run`. |
57
+ | `blurt-reblog` | Reblog (re-share) a post to the account's blog (`custom_json` reblog), or undo it. Supports `dry_run`. |
58
+ | `blurt-read-notifications` | Mark the account's notifications as read up to now (`custom_json` notify). Supports `dry_run`. |
59
+
60
+ All write tools are signed locally with the posting key, **off by default**, and exposed through stdio
61
+ by default. `BLURT_DRY_RUN_DEFAULT=true` can make omitted `dry_run` parameters preview-first without
62
+ blocking explicit execution. HTTP signing is only for explicit unsafe trusted-deployment override mode.
63
+ See [write operations](./write-operations.md).
64
+
65
+ ## Resources
66
+
67
+ Resource templates resolvable via the `fetch` tool or a resource-aware client:
68
+
69
+ - `blurt://account/{username}`
70
+ - `blurt://history/{username}?limit=&ops=vote,comment`
71
+ - `blurt://posts/{by}/{tag}?limit=` — `by` ∈ `trending|hot|created|promoted|payout|payout_comments|muted`
72
+ - `blurt://account-posts/{sort}/{account}?limit=` — `sort` ∈ `blog|feed|posts|comments|replies|payout`
73
+ - `blurt://post/{author}/{permlink}?with_comments=true`
74
+
75
+ ## Example prompts
76
+
77
+ You never tell the AI which tool to use — it picks and chains them. Start simple, then push.
78
+
79
+ **Market & network**
80
+ - "What is the current BLURT price in USD?"
81
+ - "What is Blurt's market cap and how many BLURT are in circulation?"
82
+ - "Is the Blurt chain healthy right now?"
83
+
84
+ **Accounts & wallets**
85
+ - "Show me the account `nalexadre` and convert its BLURT balance to USD."
86
+ - "How much Blurt Power does `nalexadre` have?"
87
+
88
+ **Curation**
89
+ - "How much is a 100% upvote from `nalexadre` worth, in BLURT and USD?"
90
+ - "Who are the top 5 curators on the post `nalexadre/how-ai-can-help-curation-on-blurt-1759501073717`?"
91
+
92
+ **Communities**
93
+ - "What are the most popular Blurt communities?"
94
+ - "Find a community about photography and show me its details."
95
+
96
+ **Governance**
97
+ - "List the top 10 Blurt witnesses and flag any that look inactive or behind on version."
98
+ - "Which witnesses does `nalexadre` vote for — and are they all healthy?"
99
+
100
+ **Multi-step**
101
+ - "Give me a profile of `nalexadre`: bio, the USD value of their vote, and their latest post with its vote count."
102
+ - "Compare `nalexadre`, `megadrive` and `khrom` — stake, reach and earnings — as a table."
package/docs/usage.md ADDED
@@ -0,0 +1,157 @@
1
+ # Installation & usage
2
+
3
+ For connecting a specific client (Claude, ChatGPT, Cursor, …) see the
4
+ [client compatibility matrix](./clients.md). For local signing, see
5
+ [write operations](./write-operations.md).
6
+
7
+ ## Requirements
8
+
9
+ - Node.js **>= 18** to run the server (uses native `fetch`/`AbortController`).
10
+ - Node.js **>= 20.6** for development and tests (the test runner uses `node --import tsx`).
11
+ - npm
12
+
13
+ ## Installation
14
+
15
+ For package-based local use, run the official npm package:
16
+
17
+ ```bash
18
+ npx -y -p @blurt-blockchain/blurt-mcp-server blurt-mcp-stdio
19
+ ```
20
+
21
+ For source development:
22
+
23
+ ```bash
24
+ npm install
25
+ ```
26
+
27
+ For copy-paste client configs, see [install snippets](./install-snippets.md).
28
+
29
+ ## Configuration
30
+
31
+ Copy the example env file and adjust as needed:
32
+
33
+ ```bash
34
+ cp .env.example .env
35
+ ```
36
+
37
+ | Variable | Default | Description |
38
+ | --- | --- | --- |
39
+ | `PORT` | `3000` | HTTP port Express listens on. |
40
+ | `BLURT_RPC_URLS` | a list of public Blurt nodes | Comma-separated Blurt RPC endpoints. **Provide several**: the server scores them continuously (via [`@beblurt/blurt-nodes-checker`](https://gitlab.com/beblurt/blurt-nodes-checker)) and keeps the client on the healthiest ones; offline/stale/forked nodes are dropped. |
41
+ | `BLURT_PRICE_URL` | `https://api.blurt.blog/price_info` | Price feed used by the price/market tools. |
42
+ | `LOG_LEVEL` | `info` | `debug` \| `info` \| `warn` \| `error`. |
43
+ | `NODE_ENV` | `development` | `production` switches logs to JSON output. |
44
+ | `BLURT_CHAIN_ID` | _(mainnet)_ | Optional. Target a **testnet**: set this **and** `BLURT_ADDRESS_PREFIX`. Unset = Blurt main network (dblurt default). |
45
+ | `BLURT_ADDRESS_PREFIX` | _(mainnet `BLT`)_ | Optional. Testnet address prefix; set together with `BLURT_CHAIN_ID`. |
46
+
47
+ Write-related variables (`BLURT_ACCOUNT`, `BLURT_POSTING_KEY`, `BLURT_WRITE_PROFILE`,
48
+ `BLURT_WRITE_TOOLS_BANNED`, `BLURT_DRY_RUN_DEFAULT`, `BLURT_ENV_FILE`) are documented in
49
+ [write operations](./write-operations.md). The intentionally unsafe HTTP-signing override is also
50
+ documented there because it changes deployment posture and should be reviewed before use.
51
+
52
+ > The `/mcp` endpoint has **no built-in authentication** and is **read-only** by default — no private
53
+ > keys required for normal HTTP operation. Authentication is planned for a future version.
54
+
55
+ ## Running the HTTP server
56
+
57
+ Development (hot reload):
58
+
59
+ ```bash
60
+ npm run dev
61
+ ```
62
+
63
+ Production:
64
+
65
+ ```bash
66
+ npm run build
67
+ npm start
68
+ ```
69
+
70
+ The server then listens on `http://localhost:<PORT>/mcp` (HTTP `POST`); `GET` and `DELETE` return
71
+ `405` (stateless mode). It also exposes cheap operational probes outside MCP:
72
+
73
+ - `GET /healthz` — process liveness;
74
+ - `GET /readyz` — readiness with non-sensitive RPC readiness counters.
75
+
76
+ > **Deploy behind a reverse proxy** (nginx, Caddy, Traefik, …). Let the proxy terminate TLS and handle
77
+ > rate limiting and `Host`/origin filtering. The public hosted endpoint intentionally remains anonymous
78
+ > and read-only. Do not expose write/signing over HTTP unless you have deliberately enabled the unsafe
79
+ > trusted-deployment override described in [write operations](./write-operations.md#advanced-unsafe-http-signing-for-trusted-deployments).
80
+ > See [SECURITY.md](../SECURITY.md) for the rationale.
81
+
82
+ ### Inspecting
83
+
84
+ ```bash
85
+ npm run inspector
86
+ ```
87
+
88
+ Launches the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) against the built server.
89
+
90
+ ## Connecting an MCP client
91
+
92
+ The server speaks MCP over **Streamable HTTP** at `POST /mcp` (stateless: no session id). Use the
93
+ hosted instance (`https://mcp.blurt-blockchain.com/mcp`) or your own (`http://localhost:<PORT>/mcp`).
94
+
95
+ **Apps with native remote-MCP support (Claude, ChatGPT, Grok, Mistral, …):** add a custom/remote
96
+ connector and paste the URL — that's it.
97
+
98
+ **Desktop apps configured via a JSON file (e.g. Claude Desktop's `claude_desktop_config.json`)** speak
99
+ **stdio**, so bridge to the HTTP server with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote)
100
+ — `npx` fetches it on first run:
101
+
102
+ ```json
103
+ {
104
+ "mcpServers": {
105
+ "blurt": {
106
+ "command": "npx",
107
+ "args": ["-y", "mcp-remote", "https://mcp.blurt-blockchain.com/mcp"]
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ Swap the URL for `http://localhost:<PORT>/mcp` to point at a server you run yourself.
114
+
115
+ ## Run locally as a stdio server
116
+
117
+ Prefer a fully local server — no HTTP, no bridge, no hosted dependency? Use the package bin:
118
+
119
+ ```bash
120
+ npx -y -p @blurt-blockchain/blurt-mcp-server blurt-mcp-stdio
121
+ ```
122
+
123
+ Desktop config example:
124
+
125
+ ```json
126
+ {
127
+ "mcpServers": {
128
+ "blurt": {
129
+ "command": "npx",
130
+ "args": ["-y", "-p", "@blurt-blockchain/blurt-mcp-server", "blurt-mcp-stdio"]
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ When developing from a source checkout instead, build once and point your client at the compiled file:
137
+
138
+ ```bash
139
+ npm install && npm run build
140
+ ```
141
+
142
+ ```json
143
+ {
144
+ "mcpServers": {
145
+ "blurt": {
146
+ "command": "node",
147
+ "args": ["/absolute/path/to/blurt-mcp-server/dist/server-stdio.js"]
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ It registers the same 25 read tools and uses the same RPC node selection as the HTTP server; logs go to
154
+ `stderr` so they never interfere with the protocol on `stdout`. (For development: `npm run dev:stdio`.)
155
+
156
+ To enable **local signing** (claim rewards, …) on this stdio server, see
157
+ [write operations](./write-operations.md).
@@ -0,0 +1,223 @@
1
+ # Write operations (signing) — opt-in, local by default
2
+
3
+ Write tools (`blurt-claim-rewards`, `blurt-upvote`, `blurt-comment`, `blurt-post`, `blurt-follow`,
4
+ `blurt-mute`, `blurt-subscribe-community`, `blurt-reblog`, `blurt-read-notifications`) are **off by
5
+ default**. They are registered **only** on the stdio server by default, and **only** when a valid
6
+ **posting** authority is configured. The normal HTTP server refuses to start if a posting key is
7
+ present; an explicitly unsafe HTTP override exists only for trusted operator-controlled deployments
8
+ (see [Advanced: unsafe HTTP signing for trusted deployments](#advanced-unsafe-http-signing-for-trusted-deployments)).
9
+
10
+ Read [SECURITY.md](../SECURITY.md) for the full threat model and the principles every write tool follows.
11
+
12
+ ## Which key — delegated posting authority (recommended)
13
+
14
+ `BLURT_ACCOUNT` is the account you act *as*. `BLURT_POSTING_KEY` may be **either**:
15
+
16
+ 1. **A delegated account's posting key (recommended).** Create/own a separate account, grant it
17
+ **posting authority** over `BLURT_ACCOUNT` (add it to your posting `account_auths` — most wallets
18
+ call this "posting authority"), and configure the MCP with **that account's** posting key. Your own
19
+ key is never shared, and you can **revoke** access in one operation (remove the authority) without
20
+ rotating any key.
21
+ 2. **Your account's own posting key.** Simpler, but to revoke it you must change your posting key.
22
+
23
+ On startup the server validates that the key has posting authority over `BLURT_ACCOUNT` — directly, or
24
+ through a delegated account — and **refuses owner/active keys**. The posting authority cannot move funds.
25
+
26
+ ## Recommended setup — key in a file you control, outside the repo
27
+
28
+ Put the secret in a file outside the project (e.g. `~/.config/blurt-mcp/secret.env`, `chmod 600`), and
29
+ point the stdio launcher at it with `BLURT_ENV_FILE` — the launcher itself carries **no secret**:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "blurt": {
35
+ "command": "node",
36
+ "args": ["/absolute/path/to/blurt-mcp-server/dist/server-stdio.js"],
37
+ "env": { "BLURT_ENV_FILE": "/home/you/.config/blurt-mcp/secret.env" }
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ```bash
44
+ # ~/.config/blurt-mcp/secret.env (chmod 600)
45
+ BLURT_ACCOUNT=youraccount
46
+ BLURT_POSTING_KEY=5J...
47
+ # recommended for new users — claim rewards + upvote only:
48
+ BLURT_WRITE_PROFILE=curator
49
+ # optional — subtract individual tools from the selected profile:
50
+ # BLURT_WRITE_TOOLS_BANNED=upvote
51
+ # optional neutral safety default — omitted dry_run parameters preview first:
52
+ # BLURT_DRY_RUN_DEFAULT=true
53
+ ```
54
+
55
+ The server loads `BLURT_ENV_FILE` (or, if unset, the project's `.env`) regardless of the working
56
+ directory the desktop app launches it from. Variables already set in the launcher's `env` block take
57
+ precedence over the file, so you can also place the values directly in `env` if you prefer.
58
+
59
+ > Do **not** put the posting key in the project's `.env`: the HTTP server would then refuse to start,
60
+ > and the secret would live inside the working tree. Keep it in a file outside the repo.
61
+
62
+ ## Guarantees
63
+
64
+ - Only the **posting** key is accepted (active/owner are refused; it cannot move funds). The key is
65
+ used solely for local signing — never sent to the network, logs, or other dependencies.
66
+ - Write tools are registered **only** on the stdio server by default, gated by the validated key and
67
+ the `BLURT_WRITE_TOOLS_BANNED` denylist. The HTTP server refuses to start with a key unless the
68
+ operator explicitly enables the unsafe trusted-deployment override below.
69
+ - Calls are rate-limited (per tool).
70
+
71
+ Every write tool supports `dry_run: true` to preview **without** broadcasting, and your AI client also
72
+ prompts you to approve each tool call before it runs. Operators who prefer preview-first behavior can
73
+ set `BLURT_DRY_RUN_DEFAULT=true`; omitted `dry_run` parameters then default to preview mode, while an
74
+ explicit `dry_run: false` still executes the operation.
75
+
76
+ ### Neutral infrastructure boundary
77
+
78
+ The official server intentionally does **not** enforce content, account, tag, community or social-usage
79
+ policy. It validates signing authority, protects unsafe transports by default, lets operators choose
80
+ which write tools are registered, and can default calls to dry-run mode. It does not implement allow/block
81
+ lists for accounts or communities, posting quotas, or moderation policy files; those belong in clients,
82
+ wrappers, gateways, external signers, custom deployments, or forks when an operator needs them. See
83
+ [ADR 0001](./adr/0001-neutral-infrastructure.md).
84
+
85
+ ### Enabling tools with capability profiles
86
+
87
+ `BLURT_WRITE_PROFILE` is the recommended control for new deployments. It enables a semantic set of
88
+ capabilities, so operators do not need to maintain a long comma-separated list of every tool and do not
89
+ need to edit config just because a future release adds a tool that clearly belongs to the same profile.
90
+
91
+ If `BLURT_WRITE_PROFILE` is **unset**, the server preserves the historical behavior for backward
92
+ compatibility: all current write tools are enabled, and `BLURT_WRITE_TOOLS_BANNED` subtracts specific
93
+ ones.
94
+
95
+ Recommended starting point:
96
+
97
+ ```dotenv
98
+ BLURT_WRITE_PROFILE=curator
99
+ ```
100
+
101
+ Profiles:
102
+
103
+ | Profile | Enables | Intended operator posture |
104
+ | --- | --- | --- |
105
+ | `none` | no write tools | Keep a key configured but temporarily expose no write surface. |
106
+ | `curator` | `claim-rewards`, `upvote` | Safer new-user default: rewards + voting only. |
107
+ | `social` | `curator` plus `follow`, `mute`, `subscribe-community`, `read-notifications`, `reblog` | Social/community actions, but no original text publishing. |
108
+ | `publisher` | all current publishing/social/reward tools | Trusted local assistant that may comment and publish posts. Future high-risk tools should be classified deliberately before joining this profile. |
109
+ | `full` | every write tool in this release | Explicit full-access mode; equivalent to legacy unset-profile behavior for current tools. |
110
+
111
+ `BLURT_WRITE_TOOLS_BANNED` remains supported as a backward-compatible subtractive control. It always
112
+ removes individual tools from whichever profile is active (or from legacy `full` mode when no profile
113
+ is set). For example, a social operator that wants to allow follows/community/reblogs but not upvotes:
114
+
115
+ ```dotenv
116
+ BLURT_WRITE_PROFILE=social
117
+ BLURT_WRITE_TOOLS_BANNED=upvote
118
+ ```
119
+
120
+ Use the **tool name** column below for denylist entries. Unknown denylist names are ignored so old
121
+ configuration remains forward-compatible across releases; an unknown `BLURT_WRITE_PROFILE` fails
122
+ closed at startup.
123
+
124
+ | Tool | Tool name | Operation | Rate cap | Profiles |
125
+ | --- | --- | --- | ---: | --- |
126
+ | `blurt-claim-rewards` | `claim-rewards` | `claim_reward_balance` | 6 / hour | `curator`, `social`, `publisher`, `full` |
127
+ | `blurt-upvote` | `upvote` | `vote` | 30 / hour | `curator`, `social`, `publisher`, `full` |
128
+ | `blurt-comment` | `comment` | `comment` (reply) | 10 / hour | `publisher`, `full` |
129
+ | `blurt-post` | `post` | `comment` (top-level) | 10 / hour | `publisher`, `full` |
130
+ | `blurt-follow` | `follow` | `custom_json` follow | 30 / hour | `social`, `publisher`, `full` |
131
+ | `blurt-mute` | `mute` | `custom_json` follow/ignore | 30 / hour | `social`, `publisher`, `full` |
132
+ | `blurt-subscribe-community` | `subscribe-community` | `custom_json` community | 30 / hour | `social`, `publisher`, `full` |
133
+ | `blurt-reblog` | `reblog` | `custom_json` reblog | 30 / hour | `social`, `publisher`, `full` |
134
+ | `blurt-read-notifications` | `read-notifications` | `custom_json` notify | 30 / hour | `social`, `publisher`, `full` |
135
+
136
+ ### Advanced: unsafe HTTP signing for trusted deployments
137
+
138
+ The default and recommended signing mode is still **local stdio**. However, experienced operators who
139
+ run a private, authenticated, access-controlled deployment may deliberately opt in to exposing the same
140
+ write tools over the HTTP MCP endpoint.
141
+
142
+ This is intentionally hard to enable. You must configure a valid write context (`BLURT_ACCOUNT` and
143
+ `BLURT_POSTING_KEY`) and set this exact environment variable/value on the HTTP server process:
144
+
145
+ ```dotenv
146
+ BLURT_UNSAFE_ALLOW_HTTP_SIGNING_WITH_POSTING_KEY=I_ACCEPT_FULL_RESPONSIBILITY_FOR_EXPOSING_BLURT_WRITE_TOOLS_OVER_HTTP
147
+ ```
148
+
149
+ Any other value is ignored and the HTTP server still refuses to start with `BLURT_POSTING_KEY` set.
150
+ When the override is active, startup prints a large `UNSAFE HTTP SIGNING ENABLED` warning to `stderr`.
151
+ The override does **not** weaken the other write policies: active/owner keys are still refused, posting
152
+ authority is still validated, `BLURT_WRITE_TOOLS_BANNED` still applies, and rate caps still apply.
153
+
154
+ Use this only when the HTTP endpoint is protected by your own authentication, TLS, network isolation,
155
+ reverse-proxy controls, monitoring, and operational procedures. Do **not** use it for the public hosted
156
+ endpoint, an anonymous service, or an unauthenticated LAN/WAN deployment. The operator accepts full
157
+ responsibility for every on-chain operation signed by that process. See [SECURITY.md](../SECURITY.md)
158
+ for the full rationale and threat model.
159
+
160
+ ## `blurt-claim-rewards`
161
+
162
+ Claims the configured account's pending author/curation rewards (`claim_reward_balance`), moving them
163
+ into the account's balance and Blurt Power. Acts only on the configured account; no parameter targets
164
+ another account. Returns the pending amounts and, when executed, the transaction id.
165
+
166
+ ## `blurt-upvote`
167
+
168
+ Upvotes a post or comment (`vote`) as the configured account.
169
+
170
+ - Parameters: `author`, `permlink`, `weight` (percent, 1-100, default 100), `dry_run`.
171
+ - Only the configured account votes; on chain, weight 100% = 10000.
172
+
173
+ ## `blurt-comment`
174
+
175
+ Posts a reply (`comment`) to a post or comment as the configured account.
176
+
177
+ - Parameters: `parent_author`, `parent_permlink`, `body` (markdown), `dry_run`.
178
+ - A unique permlink is generated automatically. The body gets a `via Blurt-MCP` footer (linking back
179
+ to this repository) appended after a blank line, and `json_metadata.app` is set to `blurt-mcp/<version>`.
180
+ - Posts are **public and permanent** — use `dry_run: true` first to review the exact final body.
181
+
182
+ ## `blurt-post`
183
+
184
+ Publishes a **new top-level post** (`comment` with an empty parent) as the configured account.
185
+
186
+ - Parameters: `title`, `body` (markdown), `tags` (1–8 lowercase tags; the first is the main category),
187
+ `dry_run`.
188
+ - A unique permlink is generated from the title. Same `via Blurt-MCP` footer and `json_metadata.app =
189
+ blurt-mcp/<version>` stamping as `blurt-comment`; the tags are stored in `json_metadata.tags`.
190
+ - Posts are **public and permanent** — use `dry_run: true` first to review the exact final post.
191
+
192
+ ## `blurt-follow`
193
+
194
+ Follows or unfollows another account (`custom_json` id `follow`).
195
+
196
+ - Parameters: `account`, `action` (`follow` | `unfollow`, default `follow`), `dry_run`.
197
+
198
+ ## `blurt-mute`
199
+
200
+ Mutes (ignores) or unmutes another account (`custom_json` id `follow`, `what: ['ignore']`), hiding its
201
+ content in compatible frontends.
202
+
203
+ - Parameters: `account`, `action` (`mute` | `unmute`, default `mute`), `dry_run`.
204
+
205
+ ## `blurt-subscribe-community`
206
+
207
+ Subscribes the account to a community, or unsubscribes from it (`custom_json` id `community`).
208
+
209
+ - Parameters: `community` (name/id, e.g. `blurt-192372`), `action` (`subscribe` | `unsubscribe`,
210
+ default `subscribe`), `dry_run`.
211
+
212
+ ## `blurt-reblog`
213
+
214
+ Reblogs (re-shares) a post to the account's blog (`custom_json` id `reblog`), or removes a prior reblog.
215
+
216
+ - Parameters: `author`, `permlink`, `undo` (default `false`), `dry_run`.
217
+
218
+ ## `blurt-read-notifications`
219
+
220
+ Marks the account's notifications as read up to now (`custom_json` id `notify`, `setLastRead`). Acts
221
+ only on the configured account; no parameter targets another account.
222
+
223
+ - Parameter: `dry_run`. Pair with `get-account-notifications` to read them first.
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@blurt-blockchain/blurt-mcp-server",
3
+ "version": "0.4.0",
4
+ "description": "Model Context Protocol (MCP) server exposing the Blurt blockchain (accounts, history, posts) over Streamable HTTP.",
5
+ "type": "module",
6
+ "author": "nalexadre - Blurt blockchain",
7
+ "license": "GPL-3.0-or-later",
8
+ "homepage": "https://gitlab.com/blurt-blockchain/blurt-mcp-server",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://gitlab.com/blurt-blockchain/blurt-mcp-server.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://gitlab.com/blurt-blockchain/blurt-mcp-server/-/issues"
15
+ },
16
+ "keywords": [
17
+ "blurt",
18
+ "blockchain",
19
+ "mcp",
20
+ "model-context-protocol",
21
+ "dblurt"
22
+ ],
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "scripts": {
27
+ "dev": "tsx watch src/server.ts",
28
+ "start": "node dist/server.js",
29
+ "start:stdio": "node dist/server-stdio.js",
30
+ "dev:stdio": "tsx src/server-stdio.ts",
31
+ "inspector": "npx @modelcontextprotocol/inspector dist/server.js",
32
+ "build": "tsc -p tsconfig.json",
33
+ "typecheck": "tsc -p tsconfig.json --noEmit",
34
+ "check:secrets": "node scripts/check-secrets.mjs",
35
+ "docs:tools": "tsx scripts/generate-tool-docs.ts",
36
+ "docs:check": "npm run docs:tools && git diff --exit-code docs/tools.generated.md",
37
+ "test": "node --import tsx --test test/uri.test.ts test/search.test.ts test/contract.test.ts test/resilience.test.ts test/write.test.ts test/ops.test.ts test/package.test.ts test/stdio.test.ts test/network.test.ts",
38
+ "test:live": "node --import tsx --test test/live.test.ts",
39
+ "test:http": "node --import tsx --test test/http.test.ts",
40
+ "smoke:http": "node scripts/smoke-http.mjs",
41
+ "test:all": "node --import tsx --test test/*.test.ts",
42
+ "release": "commit-and-tag-version",
43
+ "release:minor": "commit-and-tag-version --release-as minor",
44
+ "release:major": "commit-and-tag-version --release-as major",
45
+ "release:dry": "commit-and-tag-version --dry-run",
46
+ "pack:check": "npm run build && npm pack --dry-run",
47
+ "smoke:package": "node scripts/smoke-package.mjs"
48
+ },
49
+ "dependencies": {
50
+ "@beblurt/blurt-nodes-checker": "^2.2.0",
51
+ "@beblurt/dblurt": "^0.15.0",
52
+ "@modelcontextprotocol/sdk": "^1.29.0",
53
+ "dotenv": "^17.4.2",
54
+ "express": "^5.2.1",
55
+ "zod": "^4.4.3"
56
+ },
57
+ "devDependencies": {
58
+ "@types/express": "^5.0.6",
59
+ "@types/node": "^26.0.1",
60
+ "commit-and-tag-version": "^12.7.3",
61
+ "tsx": "^4.22.4",
62
+ "typescript": "^5.9.3"
63
+ },
64
+ "main": "dist/server.js",
65
+ "bin": {
66
+ "blurt-mcp-server": "dist/server.js",
67
+ "blurt-mcp-stdio": "dist/server-stdio.js"
68
+ },
69
+ "files": [
70
+ "dist/",
71
+ "docs/",
72
+ "README.md",
73
+ "LICENSE",
74
+ "CHANGELOG.md",
75
+ "SECURITY.md"
76
+ ]
77
+ }