@otskit/mcp
Advanced tools
| import { | ||
| createTimestamp, | ||
| listPending, | ||
| verifyTimestamp | ||
| } from "./chunk-TDZK25BZ.js"; | ||
| import { | ||
| backupDb, | ||
| getDb, | ||
| loadConfig, | ||
| upgradeTimestamp | ||
| } from "./chunk-PLEDJI67.js"; | ||
| import "./chunk-IB2AYNP4.js"; | ||
| // src/cli.ts | ||
| async function runCli(command, args) { | ||
| const config = loadConfig(); | ||
| const db = getDb(); | ||
| switch (command) { | ||
| case "stamp": { | ||
| const hash = args[0]; | ||
| if (!hash) { | ||
| process.stderr.write("Usage: ots-mcp stamp <sha256-hash>\n"); | ||
| process.exit(1); | ||
| } | ||
| const result = await createTimestamp({ hash }, db, config); | ||
| if ("error" in result) { | ||
| process.stderr.write(`Error: ${result.error} \u2014 ${result.details} | ||
| `); | ||
| process.exit(1); | ||
| } | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "upgrade": { | ||
| const id = args[0]; | ||
| if (!id) { | ||
| process.stderr.write("Usage: ots-mcp upgrade <id>\n"); | ||
| process.exit(1); | ||
| } | ||
| const result = await upgradeTimestamp({ id }, db, config); | ||
| if ("error" in result) { | ||
| process.stderr.write(`Error: ${result.error} \u2014 ${result.details} | ||
| `); | ||
| process.exit(1); | ||
| } | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "verify": { | ||
| const id = args[0]; | ||
| if (!id) { | ||
| process.stderr.write("Usage: ots-mcp verify <id>\n"); | ||
| process.exit(1); | ||
| } | ||
| const result = await verifyTimestamp({ id }, db, config); | ||
| if ("error" in result) { | ||
| process.stderr.write(`Error: ${result.error} \u2014 ${result.details} | ||
| `); | ||
| process.exit(1); | ||
| } | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "list": { | ||
| const status = args[0] ?? "pending"; | ||
| const result = listPending({ status }, db, config); | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "check-pending": { | ||
| const { items } = listPending({ status: "pending", limit: 200, due_now: true }, db, config); | ||
| process.stderr.write(`Processing ${items.length} pending stamps... | ||
| `); | ||
| for (const record of items) { | ||
| const result = await upgradeTimestamp({ id: record.id }, db, config); | ||
| const statusStr = "status" in result ? result.status : `error:${result.error}`; | ||
| process.stderr.write(`${record.id.slice(0, 8)}: ${statusStr} | ||
| `); | ||
| } | ||
| process.exit(0); | ||
| } | ||
| case "backup": { | ||
| const dest = args[0] ?? `ots-mcp-backup-${Date.now()}.sqlite`; | ||
| backupDb(dest); | ||
| process.stdout.write(`Backup saved to ${dest} | ||
| `); | ||
| break; | ||
| } | ||
| case "scheduler": { | ||
| const { runScheduler } = await import("./scheduler-B4HFMIOK.js"); | ||
| await runScheduler(args); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| export { | ||
| runCli | ||
| }; |
| import { | ||
| escapeXml, | ||
| which | ||
| } from "./chunk-IB2AYNP4.js"; | ||
| // src/scheduler/install.ts | ||
| import { execFileSync } from "child_process"; | ||
| import { mkdtempSync, rmSync, writeFileSync } from "fs"; | ||
| import { tmpdir } from "os"; | ||
| import { join } from "path"; | ||
| async function installScheduler(args) { | ||
| const intervalIdx = args.indexOf("--interval"); | ||
| const parsedInterval = intervalIdx !== -1 ? parseInt(args[intervalIdx + 1] ?? "30") : 30; | ||
| const interval = Math.max(1, Math.min(1440, Number.isFinite(parsedInterval) ? parsedInterval : 30)); | ||
| const bin = which("ots-mcp") ?? process.argv[1]; | ||
| if (process.platform === "win32") { | ||
| const workDir = mkdtempSync(join(tmpdir(), "ots-mcp-")); | ||
| const xmlPath = join(workDir, "task.xml"); | ||
| try { | ||
| writeFileSync(xmlPath, `<?xml version="1.0"?> | ||
| <Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> | ||
| <Triggers><TimeTrigger> | ||
| <Repetition><Interval>PT${interval}M</Interval><StopAtDurationEnd>false</StopAtDurationEnd></Repetition> | ||
| <StartBoundary>2020-01-01T00:00:00</StartBoundary><Enabled>true</Enabled> | ||
| </TimeTrigger></Triggers> | ||
| <Actions><Exec> | ||
| <Command>${escapeXml(bin)}</Command> | ||
| <Arguments>check-pending</Arguments> | ||
| </Exec></Actions> | ||
| </Task>`); | ||
| execFileSync("schtasks", ["/create", "/tn", "ots-mcp-check-pending", "/xml", xmlPath, "/f"]); | ||
| } finally { | ||
| rmSync(workDir, { recursive: true, force: true }); | ||
| } | ||
| process.stdout.write(`Scheduler installed: runs every ${interval} minutes | ||
| `); | ||
| } else { | ||
| process.stdout.write(`Add to crontab (run: crontab -e): | ||
| `); | ||
| process.stdout.write(`*/${interval} * * * * "${bin}" check-pending | ||
| `); | ||
| } | ||
| } | ||
| export { | ||
| installScheduler | ||
| }; |
| // src/scheduler/index.ts | ||
| async function runScheduler(args) { | ||
| const [sub, ...rest] = args; | ||
| switch (sub) { | ||
| case "install": { | ||
| const { installScheduler } = await import("./install-A7BHHPUP.js"); | ||
| await installScheduler(rest); | ||
| break; | ||
| } | ||
| case "remove": { | ||
| const { removeScheduler } = await import("./remove-BGFQRDX3.js"); | ||
| await removeScheduler(); | ||
| break; | ||
| } | ||
| case "status": { | ||
| const { statusScheduler } = await import("./status-M6A2RG7G.js"); | ||
| await statusScheduler(); | ||
| break; | ||
| } | ||
| default: | ||
| process.stderr.write("Usage: ots-mcp scheduler install [--interval N] | remove | status\n"); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| export { | ||
| runScheduler | ||
| }; |
+1
-1
@@ -68,3 +68,3 @@ #!/usr/bin/env node | ||
| case "scheduler": { | ||
| const { runCli } = await import("./cli-CQHIKXES.js"); | ||
| const { runCli } = await import("./cli-CJKURFLC.js"); | ||
| await runCli(command, args); | ||
@@ -71,0 +71,0 @@ break; |
+1
-1
| { | ||
| "name": "@otskit/mcp", | ||
| "mcpName": "io.github.AlexAlves87/otskit-mcp", | ||
| "version": "0.8.0", | ||
| "version": "0.8.1", | ||
| "license": "MIT", | ||
@@ -6,0 +6,0 @@ "description": "OpenTimestamps MCP server — stamp, upgrade, verify via AI agents", |
+1
-0
@@ -13,2 +13,3 @@ <p align="center"> | ||
| [](https://codecov.io/gh/OTSkit/OTSkit-MCP) | ||
| [](https://sonarcloud.io/summary/new_code?id=OTSkit_OTSkit-MCP) | ||
| [](LICENSE) | ||
@@ -15,0 +16,0 @@ [](https://glama.ai/mcp/servers/OTSkit/OTSkit-MCP) |
| import { | ||
| createTimestamp, | ||
| listPending, | ||
| verifyTimestamp | ||
| } from "./chunk-TDZK25BZ.js"; | ||
| import { | ||
| backupDb, | ||
| getDb, | ||
| loadConfig, | ||
| upgradeTimestamp | ||
| } from "./chunk-PLEDJI67.js"; | ||
| import "./chunk-IB2AYNP4.js"; | ||
| // src/cli.ts | ||
| async function runCli(command, args) { | ||
| const config = loadConfig(); | ||
| const db = getDb(); | ||
| switch (command) { | ||
| case "stamp": { | ||
| const hash = args[0]; | ||
| if (!hash) { | ||
| process.stderr.write("Usage: ots-mcp stamp <sha256-hash>\n"); | ||
| process.exit(1); | ||
| } | ||
| const result = await createTimestamp({ hash }, db, config); | ||
| if ("error" in result) { | ||
| process.stderr.write(`Error: ${result.error} \u2014 ${result.details} | ||
| `); | ||
| process.exit(1); | ||
| } | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "upgrade": { | ||
| const id = args[0]; | ||
| if (!id) { | ||
| process.stderr.write("Usage: ots-mcp upgrade <id>\n"); | ||
| process.exit(1); | ||
| } | ||
| const result = await upgradeTimestamp({ id }, db, config); | ||
| if ("error" in result) { | ||
| process.stderr.write(`Error: ${result.error} \u2014 ${result.details} | ||
| `); | ||
| process.exit(1); | ||
| } | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "verify": { | ||
| const id = args[0]; | ||
| if (!id) { | ||
| process.stderr.write("Usage: ots-mcp verify <id>\n"); | ||
| process.exit(1); | ||
| } | ||
| const result = await verifyTimestamp({ id }, db, config); | ||
| if ("error" in result) { | ||
| process.stderr.write(`Error: ${result.error} \u2014 ${result.details} | ||
| `); | ||
| process.exit(1); | ||
| } | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "list": { | ||
| const status = args[0] ?? "pending"; | ||
| const result = listPending({ status }, db, config); | ||
| process.stdout.write(JSON.stringify(result, null, 2) + "\n"); | ||
| break; | ||
| } | ||
| case "check-pending": { | ||
| const { items } = listPending({ status: "pending", limit: 200, due_now: true }, db, config); | ||
| process.stderr.write(`Processing ${items.length} pending stamps... | ||
| `); | ||
| for (const record of items) { | ||
| const result = await upgradeTimestamp({ id: record.id }, db, config); | ||
| const statusStr = "status" in result ? result.status : `error:${result.error}`; | ||
| process.stderr.write(`${record.id.slice(0, 8)}: ${statusStr} | ||
| `); | ||
| } | ||
| process.exit(0); | ||
| } | ||
| case "backup": { | ||
| const dest = args[0] ?? `ots-mcp-backup-${Date.now()}.sqlite`; | ||
| backupDb(dest); | ||
| process.stdout.write(`Backup saved to ${dest} | ||
| `); | ||
| break; | ||
| } | ||
| case "scheduler": { | ||
| const { runScheduler } = await import("./scheduler-7LNXMI7L.js"); | ||
| await runScheduler(args); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| export { | ||
| runCli | ||
| }; |
| import { | ||
| escapeXml, | ||
| which | ||
| } from "./chunk-IB2AYNP4.js"; | ||
| // src/scheduler/install.ts | ||
| import { execFileSync } from "child_process"; | ||
| import { writeFileSync } from "fs"; | ||
| import { join } from "path"; | ||
| async function installScheduler(args) { | ||
| const intervalIdx = args.indexOf("--interval"); | ||
| const parsedInterval = intervalIdx !== -1 ? parseInt(args[intervalIdx + 1] ?? "30") : 30; | ||
| const interval = Math.max(1, Math.min(1440, Number.isFinite(parsedInterval) ? parsedInterval : 30)); | ||
| const bin = which("ots-mcp") ?? process.argv[1]; | ||
| if (process.platform === "win32") { | ||
| const xmlPath = join(process.env.TEMP ?? "", "ots-mcp-task.xml"); | ||
| writeFileSync(xmlPath, `<?xml version="1.0"?> | ||
| <Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> | ||
| <Triggers><TimeTrigger> | ||
| <Repetition><Interval>PT${interval}M</Interval><StopAtDurationEnd>false</StopAtDurationEnd></Repetition> | ||
| <StartBoundary>2020-01-01T00:00:00</StartBoundary><Enabled>true</Enabled> | ||
| </TimeTrigger></Triggers> | ||
| <Actions><Exec> | ||
| <Command>${escapeXml(bin)}</Command> | ||
| <Arguments>check-pending</Arguments> | ||
| </Exec></Actions> | ||
| </Task>`); | ||
| execFileSync("schtasks", ["/create", "/tn", "ots-mcp-check-pending", "/xml", xmlPath, "/f"]); | ||
| process.stdout.write(`Scheduler installed: runs every ${interval} minutes | ||
| `); | ||
| } else { | ||
| process.stdout.write(`Add to crontab (run: crontab -e): | ||
| `); | ||
| process.stdout.write(`*/${interval} * * * * "${bin}" check-pending | ||
| `); | ||
| } | ||
| } | ||
| export { | ||
| installScheduler | ||
| }; |
| // src/scheduler/index.ts | ||
| async function runScheduler(args) { | ||
| const [sub, ...rest] = args; | ||
| switch (sub) { | ||
| case "install": { | ||
| const { installScheduler } = await import("./install-YUKVAS5Q.js"); | ||
| await installScheduler(rest); | ||
| break; | ||
| } | ||
| case "remove": { | ||
| const { removeScheduler } = await import("./remove-BGFQRDX3.js"); | ||
| await removeScheduler(); | ||
| break; | ||
| } | ||
| case "status": { | ||
| const { statusScheduler } = await import("./status-M6A2RG7G.js"); | ||
| await statusScheduler(); | ||
| break; | ||
| } | ||
| default: | ||
| process.stderr.write("Usage: ots-mcp scheduler install [--interval N] | remove | status\n"); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| export { | ||
| runScheduler | ||
| }; |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 2 instances
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 2 instances
58375
0.61%1453
0.41%113
0.89%22
-4.35%