rubien-mcp-server 0.1.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/LICENSE +202 -0
- package/README.md +180 -0
- package/dist/auth.js +36 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.js +140 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +121 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas.js +166 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.js +33 -0
- package/dist/server.js.map +1 -0
- package/dist/toolHelpers.js +48 -0
- package/dist/toolHelpers.js.map +1 -0
- package/dist/tools/annotations.js +13 -0
- package/dist/tools/annotations.js.map +1 -0
- package/dist/tools/citations.js +44 -0
- package/dist/tools/citations.js.map +1 -0
- package/dist/tools/io.js +50 -0
- package/dist/tools/io.js.map +1 -0
- package/dist/tools/pdf.js +147 -0
- package/dist/tools/pdf.js.map +1 -0
- package/dist/tools/properties.js +247 -0
- package/dist/tools/properties.js.map +1 -0
- package/dist/tools/references.js +207 -0
- package/dist/tools/references.js.map +1 -0
- package/dist/tools/sync.js +10 -0
- package/dist/tools/sync.js.map +1 -0
- package/dist/tools/views.js +78 -0
- package/dist/tools/views.js.map +1 -0
- package/dist/tools/web.js +40 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/versionGuard.js +30 -0
- package/dist/versionGuard.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/tools/sync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,mMAAmM;QACrM,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAC7C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { flagsFromOptions, runCliAsTool } from "../toolHelpers.js";
|
|
3
|
+
export function registerViewTools(server) {
|
|
4
|
+
server.registerTool("rubien_views_list", {
|
|
5
|
+
title: "List saved views",
|
|
6
|
+
description: "List saved database views (persisted filter/sort/group configurations). Returns DatabaseViewDTO[].",
|
|
7
|
+
inputSchema: {},
|
|
8
|
+
annotations: { readOnlyHint: true },
|
|
9
|
+
}, async () => runCliAsTool(["views"]));
|
|
10
|
+
server.registerTool("rubien_views_create", {
|
|
11
|
+
title: "Create saved view",
|
|
12
|
+
description: "Create a new saved view. filters / sorts / groupBy must be valid JSON matching the view configuration schema (mirrors what the GUI editor produces). Use rubien_views_list first to see the shape.",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
name: z.string(),
|
|
15
|
+
filters: z
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("JSON string: ViewFilter[]"),
|
|
19
|
+
sorts: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("JSON string: ViewSort[]"),
|
|
23
|
+
groupBy: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("JSON string: GroupConfig"),
|
|
27
|
+
},
|
|
28
|
+
}, async ({ name, filters, sorts, groupBy }) => runCliAsTool([
|
|
29
|
+
"views",
|
|
30
|
+
"--create",
|
|
31
|
+
...flagsFromOptions({
|
|
32
|
+
"--name": name,
|
|
33
|
+
"--filters": filters,
|
|
34
|
+
"--sorts": sorts,
|
|
35
|
+
"--group-by": groupBy,
|
|
36
|
+
}),
|
|
37
|
+
]));
|
|
38
|
+
server.registerTool("rubien_views_delete", {
|
|
39
|
+
title: "Delete saved view",
|
|
40
|
+
description: "Remove a saved view by ID.",
|
|
41
|
+
inputSchema: { id: z.number().int() },
|
|
42
|
+
annotations: { destructiveHint: true },
|
|
43
|
+
}, async ({ id }) => runCliAsTool(["views", "--delete", "--id", String(id)]));
|
|
44
|
+
server.registerTool("rubien_views_rename", {
|
|
45
|
+
title: "Rename saved view",
|
|
46
|
+
description: "Change a saved view's name.",
|
|
47
|
+
inputSchema: { id: z.number().int(), name: z.string() },
|
|
48
|
+
}, async ({ id, name }) => runCliAsTool([
|
|
49
|
+
"views",
|
|
50
|
+
"--rename",
|
|
51
|
+
"--id",
|
|
52
|
+
String(id),
|
|
53
|
+
"--name",
|
|
54
|
+
name,
|
|
55
|
+
]));
|
|
56
|
+
server.registerTool("rubien_views_query", {
|
|
57
|
+
title: "Query a saved view",
|
|
58
|
+
description: "Run a saved view's filter/sort config and return the matching references. Equivalent to opening the view in the GUI.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
id: z.number().int(),
|
|
61
|
+
limit: z
|
|
62
|
+
.number()
|
|
63
|
+
.int()
|
|
64
|
+
.positive()
|
|
65
|
+
.max(1000)
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Result cap (default 100)"),
|
|
68
|
+
},
|
|
69
|
+
annotations: { readOnlyHint: true },
|
|
70
|
+
}, async ({ id, limit }) => runCliAsTool([
|
|
71
|
+
"views",
|
|
72
|
+
"--query",
|
|
73
|
+
"--id",
|
|
74
|
+
String(id),
|
|
75
|
+
...flagsFromOptions({ "--limit": limit }),
|
|
76
|
+
]));
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/tools/views.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { flagsFromOptions, runCliAsTool } from "../toolHelpers.js";
|
|
3
|
+
export function registerWebTools(server) {
|
|
4
|
+
server.registerTool("rubien_web_get", {
|
|
5
|
+
title: "Read the extracted body of a clipped web reference",
|
|
6
|
+
description: "Return the extracted readable text of a clipped web page reference that is already in the library. This is library-only — it does NOT fetch from the network; it returns the same text the in-app WebReader shows. Use `start` (character offset) and `maxChars` (default 50000) to paginate long pages — `contentLength` tells you the total decoded body length. The `contentFormat` field is `\"markdown\"` (most pages, post-extraction) or `\"html\"` (a small number of pages where the clipper preserved markup). For HTML, treat `content` as a fragment, not a full document. To see the user's highlights/notes on the page, call `rubien_web_annotations` for the same reference. Errors when the reference doesn't exist or has no web content (e.g. PDF-only references).",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
referenceId: z.number().int().describe("Reference ID"),
|
|
9
|
+
maxChars: z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.positive()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Cap returned characters (default 50000). Truncation is at the character boundary."),
|
|
15
|
+
start: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.nonnegative()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Character offset into the decoded body (default 0). Past end-of-content returns content=\"\" with truncated=false."),
|
|
21
|
+
},
|
|
22
|
+
annotations: { readOnlyHint: true },
|
|
23
|
+
}, async (args) => {
|
|
24
|
+
const cliArgs = ["web", "get", String(args.referenceId)];
|
|
25
|
+
cliArgs.push(...flagsFromOptions({
|
|
26
|
+
"--max-chars": args.maxChars,
|
|
27
|
+
"--start": args.start,
|
|
28
|
+
}));
|
|
29
|
+
return runCliAsTool(cliArgs);
|
|
30
|
+
});
|
|
31
|
+
server.registerTool("rubien_web_annotations", {
|
|
32
|
+
title: "List web-page annotations for a reference",
|
|
33
|
+
description: "Return the highlights, underlines, and anchored notes the user has made on a clipped web reference. This is the web-page counterpart to `rubien_annotations_list` (which covers PDF annotations only). Each annotation carries `anchorText` (the highlighted string — also what the sidebar displays), `noteText` (the user's attached note, if any), and `prefixText` / `suffixText` (the surrounding text that disambiguates the location). Together `prefixText` / `anchorText` / `suffixText` form a W3C TextQuoteSelector — use them to locate each highlight inside the body returned by `rubien_web_get`. Empty array when the reference has no web annotations or the reference ID doesn't exist (not an error).",
|
|
34
|
+
inputSchema: {
|
|
35
|
+
referenceId: z.number().int().describe("Reference ID"),
|
|
36
|
+
},
|
|
37
|
+
annotations: { readOnlyHint: true },
|
|
38
|
+
}, async ({ referenceId }) => runCliAsTool(["web", "annotations", String(referenceId)]));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/tools/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,oDAAoD;QAC3D,WAAW,EACT,wvBAAwvB;QAC1vB,WAAW,EAAE;YACX,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;YACtD,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,QAAQ,EAAE;iBACV,QAAQ,EAAE;iBACV,QAAQ,CACP,mFAAmF,CACpF;YACH,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,WAAW,EAAE;iBACb,QAAQ,EAAE;iBACV,QAAQ,CACP,oHAAoH,CACrH;SACJ;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,OAAO,GAAa,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CACV,GAAG,gBAAgB,CAAC;YAClB,aAAa,EAAE,IAAI,CAAC,QAAQ;YAC5B,SAAS,EAAE,IAAI,CAAC,KAAK;SACtB,CAAC,CACH,CAAC;QACF,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,KAAK,EAAE,2CAA2C;QAClD,WAAW,EACT,0rBAA0rB;QAC5rB,WAAW,EAAE;YACX,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;SACvD;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CACxB,YAAY,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAC5D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The minimum rubien-cli build this server requires. Equals the release build
|
|
3
|
+
* that first shipped the `version` subcommand. Bump only when a future server
|
|
4
|
+
* release genuinely needs a newer CLI feature; the released CLI's build must
|
|
5
|
+
* always be >= this value.
|
|
6
|
+
*/
|
|
7
|
+
export const MIN_CLI_BUILD = 8;
|
|
8
|
+
const RELEASES = "https://github.com/devzhk/Rubien-releases/releases";
|
|
9
|
+
/** Pure decision: is the discovered CLI new enough? `info` is null when the
|
|
10
|
+
* CLI has no `version` subcommand (i.e. predates this mechanism). */
|
|
11
|
+
export function evaluateCliVersion(info, minBuild) {
|
|
12
|
+
if (info === null) {
|
|
13
|
+
return {
|
|
14
|
+
ok: false,
|
|
15
|
+
message: `rubien-mcp-server: cannot determine rubien-cli version ` +
|
|
16
|
+
`(your rubien-cli predates the 'version' command). ` +
|
|
17
|
+
`Update Rubien.app (Mac) or download a newer rubien-cli from ${RELEASES} (Linux).`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (info.build < minBuild) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
message: `rubien-mcp-server: installed rubien-cli is build ${info.build}, ` +
|
|
24
|
+
`but this server needs build >= ${minBuild}. ` +
|
|
25
|
+
`Update Rubien.app (Mac) or download a newer rubien-cli from ${RELEASES} (Linux).`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return { ok: true };
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=versionGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versionGuard.js","sourceRoot":"","sources":["../src/versionGuard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAY/B,MAAM,QAAQ,GAAG,oDAAoD,CAAC;AAEtE;sEACsE;AACtE,MAAM,UAAU,kBAAkB,CAChC,IAAuB,EACvB,QAAgB;IAEhB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,yDAAyD;gBACzD,oDAAoD;gBACpD,+DAA+D,QAAQ,WAAW;SACrF,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,oDAAoD,IAAI,CAAC,KAAK,IAAI;gBAClE,kCAAkC,QAAQ,IAAI;gBAC9C,+DAA+D,QAAQ,WAAW;SACrF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rubien-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server wrapping rubien-cli so Claude Code and claude.ai can manage the Rubien reference library.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "devzhk",
|
|
7
|
+
"homepage": "https://github.com/devzhk/Rubien-releases#readme",
|
|
8
|
+
"repository": { "type": "git", "url": "git+https://github.com/devzhk/Rubien-releases.git" },
|
|
9
|
+
"bugs": { "url": "https://github.com/devzhk/Rubien-releases/issues" },
|
|
10
|
+
"keywords": ["mcp", "model-context-protocol", "rubien", "reference-manager", "citations"],
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"rubien-mcp-server": "dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsc --watch",
|
|
24
|
+
"start": "node dist/index.js",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"prepublishOnly": "npm run build && npm test"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
31
|
+
"zod": "^3.23.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^22.0.0",
|
|
35
|
+
"typescript": "^5.5.0",
|
|
36
|
+
"vitest": "^2.0.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
}
|
|
41
|
+
}
|