bach-box-mcp 0.1.0 → 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.
Files changed (3) hide show
  1. package/data/data.json +28 -0
  2. package/index.js +20 -92
  3. package/package.json +4 -6
package/data/data.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "files": [
3
+ {
4
+ "id": "f1",
5
+ "name": "Acme_MSA.pdf",
6
+ "path": "/Contracts/Acme_MSA.pdf",
7
+ "text": "MASTER SERVICES AGREEMENT between Acme Commerce and Stark Logistics. Term: 24 months, auto-renew 12 months. Liability cap: 12 months of fees. Termination for convenience: 60 days notice. Governing law: Delaware."
8
+ },
9
+ {
10
+ "id": "f2",
11
+ "name": "Acme_DPA.pdf",
12
+ "path": "/Contracts/Acme_DPA.pdf",
13
+ "text": "DATA PROCESSING ADDENDUM. Processes personal data of EU data subjects. Sub-processors listed in Annex II. Cross-border transfer via SCCs. Breach notification within 72 hours."
14
+ },
15
+ {
16
+ "id": "f3",
17
+ "name": "Lannister_NDA.pdf",
18
+ "path": "/Contracts/Lannister_NDA.pdf",
19
+ "text": "MUTUAL NON-DISCLOSURE AGREEMENT. Confidentiality term 3 years. Contains a non-solicitation clause for 12 months. No non-compete."
20
+ },
21
+ {
22
+ "id": "f4",
23
+ "name": "Targaryen_SOW_2026.pdf",
24
+ "path": "/Contracts/Targaryen_SOW_2026.pdf",
25
+ "text": "STATEMENT OF WORK. Deliverables: data migration. Payment: net 30. Acceptance window 10 business days."
26
+ }
27
+ ]
28
+ }
package/index.js CHANGED
@@ -2,97 +2,25 @@
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
5
-
6
- const TOOLS = [
7
- {
8
- "name": "list_folder",
9
- "description": "List items in a folder",
10
- "inputSchema": {
11
- "type": "object",
12
- "properties": {
13
- "folder_id": {
14
- "type": "string"
15
- }
16
- }
17
- },
18
- "result": {
19
- "folder": "Contracts",
20
- "items": [
21
- {
22
- "id": "f1",
23
- "name": "Acme_MSA.pdf"
24
- },
25
- {
26
- "id": "f2",
27
- "name": "Acme_DPA.pdf"
28
- }
29
- ]
30
- }
31
- },
32
- {
33
- "name": "search_files",
34
- "description": "Search files by keyword",
35
- "inputSchema": {
36
- "type": "object",
37
- "properties": {
38
- "query": {
39
- "type": "string"
40
- }
41
- },
42
- "required": [
43
- "query"
44
- ]
45
- },
46
- "result": {
47
- "results": [
48
- {
49
- "id": "f1",
50
- "name": "Acme_MSA.pdf",
51
- "path": "/Contracts/Acme_MSA.pdf"
52
- }
53
- ]
54
- }
55
- },
56
- {
57
- "name": "get_file",
58
- "description": "Get extracted text of a file",
59
- "inputSchema": {
60
- "type": "object",
61
- "properties": {
62
- "file_id": {
63
- "type": "string"
64
- }
65
- },
66
- "required": [
67
- "file_id"
68
- ]
69
- },
70
- "result": {
71
- "id": "f1",
72
- "name": "Acme_MSA.pdf",
73
- "text": "MASTER SERVICES AGREEMENT ... Term: 24 months ... Liability cap: 12 months fees ..."
74
- }
75
- }
5
+ import { readFileSync } from "node:fs";
6
+ import { fileURLToPath } from "node:url";
7
+ import { dirname, join } from "node:path";
8
+ const DATA = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "data", "data.json"), "utf8"));
9
+ const WRITE = [];
10
+ const ACK = { };
11
+ function matches(row, q){ q=String(q||"").toLowerCase(); if(!q) return true; return Object.values(row).some(v=>String(v).toLowerCase().includes(q)); }
12
+ const TOOLS=[
13
+ {name:"list_collections",description:"List available data collections and item counts.",inputSchema:{type:"object",properties:{}},run:()=>({collections:Object.keys(DATA).map(c=>({collection:c,items:(DATA[c]||[]).length}))})},
14
+ {name:"search",description:"Full-text search within a collection (case-insensitive substring across all fields). If collection omitted, searches all.",inputSchema:{type:"object",properties:{collection:{type:"string"},query:{type:"string"}},required:["query"]},run:a=>{const cols=a.collection?[a.collection]:Object.keys(DATA);const out=[];for(const c of cols)for(const row of (DATA[c]||[]))if(matches(row,a.query))out.push({collection:c,...row});return{count:out.length,results:out};}},
15
+ {name:"get",description:"Get one item by id from a collection.",inputSchema:{type:"object",properties:{collection:{type:"string"},id:{type:"string"}},required:["collection","id"]},run:a=>{const row=(DATA[a.collection]||[]).find(r=>String(r.id)===String(a.id));return row?{collection:a.collection,...row}:{error:"not found"};}},
76
16
  ];
77
-
78
- const server = new Server(
79
- { name: "bach-box-mcp", version: "0.1.0" },
80
- { capabilities: { tools: {} } }
81
- );
82
-
83
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
84
- tools: TOOLS.map(({ name, description, inputSchema }) => ({ name, description, inputSchema })),
85
- }));
86
-
87
- server.setRequestHandler(CallToolRequestSchema, async (req) => {
88
- const tool = TOOLS.find((t) => t.name === req.params.name);
89
- if (!tool) {
90
- return { isError: true, content: [{ type: "text", text: "Unknown tool: " + req.params.name }] };
91
- }
92
- const payload = { tool: tool.name, args: req.params.arguments || {}, data: tool.result, _note: "MOCK DATA from Box (mock)" };
93
- return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
17
+ const server=new Server({name:"bach-box-mcp",version:"0.2.0"},{capabilities:{tools:{}}});
18
+ server.setRequestHandler(ListToolsRequestSchema,async()=>({tools:[...TOOLS.map(({name,description,inputSchema})=>({name,description,inputSchema})),...WRITE]}));
19
+ server.setRequestHandler(CallToolRequestSchema,async req=>{
20
+ const t=TOOLS.find(t=>t.name===req.params.name);
21
+ if(t){try{return{content:[{type:"text",text:JSON.stringify(t.run(req.params.arguments||{}),null,2)}]};}catch(e){return{isError:true,content:[{type:"text",text:"Error: "+e.message}]};}}
22
+ if(ACK[req.params.name]){const r=ACK[req.params.name](req.params.arguments||{});return{content:[{type:"text",text:JSON.stringify({...r,_note:"safe mock write, not actually performed"},null,2)}]};}
23
+ return{isError:true,content:[{type:"text",text:"Unknown tool: "+req.params.name}]};
94
24
  });
95
-
96
- const transport = new StdioServerTransport();
97
- await server.connect(transport);
98
- console.error("Box (mock)" + " MCP server (mock) running on stdio");
25
+ await server.connect(new StdioServerTransport());
26
+ console.error("bach-box-mcp (records engine) collections: "+Object.keys(DATA).join(", "));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bach-box-mcp",
3
- "version": "0.1.0",
4
- "description": "Mock Box content MCP server. List folders, search and fetch document content.",
3
+ "version": "0.2.0",
4
+ "description": "Mock box MCP with a bundled sample dataset and real search/get tools (write actions are safe mocks).",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "bach-box-mcp": "index.js"
@@ -9,18 +9,16 @@
9
9
  "main": "index.js",
10
10
  "files": [
11
11
  "index.js",
12
- "README.md"
12
+ "data"
13
13
  ],
14
14
  "engines": {
15
15
  "node": ">=18"
16
16
  },
17
17
  "keywords": [
18
18
  "mcp",
19
- "modelcontextprotocol",
20
19
  "bach",
21
20
  "bachstudio",
22
- "mock",
23
- "box"
21
+ "mock"
24
22
  ],
25
23
  "author": "bachstudio",
26
24
  "license": "MIT",