twittertools-mcp 1.1.0 → 1.1.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 (3) hide show
  1. package/README.md +4 -0
  2. package/package.json +1 -1
  3. package/server.js +6 -4
package/README.md CHANGED
@@ -47,6 +47,10 @@ Or add it to any client that reads an `mcpServers` config
47
47
 
48
48
  Requires Node 18+.
49
49
 
50
+ > Tip: `npx` resolves the latest version from the registry on every launch
51
+ > (instant once cached, a few seconds the very first time). For zero startup
52
+ > delay, `npm i -g twittertools-mcp` once and set `"command": "twittertools-mcp"`.
53
+
50
54
  ## Self-hosting
51
55
 
52
56
  Point `TWITTERTOOLS_API_BASE` at your own instance of
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twittertools-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "mcpName": "io.github.steley/twittertools-mcp",
5
5
  "description": "MCP server for twittertools.com — fetch X (Twitter) posts and threads, count and split posts with X's real rules. No login, no tracking.",
6
6
  "license": "MIT",
package/server.js CHANGED
@@ -29,9 +29,9 @@ import {
29
29
  } from "./xrules.js";
30
30
 
31
31
  const NAME = "twittertools";
32
- const VERSION = "1.1.0"; // keep in sync with package.json
32
+ const VERSION = "1.1.1"; // keep in sync with package.json
33
33
  const API_BASE = (process.env.TWITTERTOOLS_API_BASE || "https://twittertools.com").replace(/\/+$/, "");
34
- const ATTRIBUTION = "\n\nvia twittertools.com";
34
+ const VIA = "https://twittertools.com";
35
35
  const TEXT_INPUT_MAX = 100_000; // generous, but caps local work per call
36
36
 
37
37
  const urlOrIdSchema = {
@@ -152,7 +152,9 @@ async function callTool(name, args) {
152
152
  case "get_tweet": {
153
153
  const data = await callApi("tweet", { id: strArg(args, "url_or_id") });
154
154
  if (!data?.tweet) throw new Error("twittertools API returned no tweet");
155
- return textResult(JSON.stringify(data.tweet, null, 2) + ATTRIBUTION);
155
+ // attribution rides inside the JSON: clients that pretty-render tool
156
+ // results would strip a trailing signature line appended after it
157
+ return textResult(JSON.stringify({ tweet: data.tweet, via: VIA }, null, 2));
156
158
  }
157
159
  case "get_thread": {
158
160
  const data = await callApi("thread", { url: strArg(args, "url_or_id") });
@@ -160,7 +162,7 @@ async function callTool(name, args) {
160
162
  const head = data.partial
161
163
  ? `Note: this thread result is PARTIAL (${data.reason || "incomplete"}) — posts may be missing.\n\n`
162
164
  : "";
163
- return textResult(head + JSON.stringify({ count: data.tweets.length, tweets: data.tweets }, null, 2) + ATTRIBUTION);
165
+ return textResult(head + JSON.stringify({ count: data.tweets.length, tweets: data.tweets, via: VIA }, null, 2));
164
166
  }
165
167
  case "count_chars":
166
168
  return textResult(JSON.stringify(countTweet(strArg(args, "text", TEXT_INPUT_MAX)), null, 2));