shireautomations 0.0.0-stage → 0.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.
package/README.md CHANGED
@@ -1,3 +1,103 @@
1
- # Temporary Holding Version
1
+ # Shire Automations CLI
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The `shire` CLI and its MCP mode give agents and people access to Shire Automations' public catalog and workflow planning tools.
4
+
5
+ ## Install
6
+
7
+ Install the CLI:
8
+
9
+ ```sh
10
+ npm install --global shireautomations
11
+ shire --help
12
+ ```
13
+
14
+ Or run a command without a global install:
15
+
16
+ ```sh
17
+ npx --yes shireautomations tools
18
+ ```
19
+
20
+ ## JavaScript SDK
21
+
22
+ Install the package in a Node.js 20 or later project:
23
+
24
+ ```sh
25
+ npm install shireautomations
26
+ ```
27
+
28
+ Use the client to read the catalog and run a planning tool:
29
+
30
+ ```js
31
+ import { ShireAutomationsClient } from "shireautomations";
32
+
33
+ const shire = new ShireAutomationsClient();
34
+ const catalog = await shire.getCatalog();
35
+ const tools = await shire.listTools();
36
+ const result = await shire.plan("workflow-mapper", {
37
+ workflowName: "New client onboarding",
38
+ trigger: "A new client signs an agreement",
39
+ outcome: "The client is ready for kickoff",
40
+ steps: [
41
+ { name: "Collect intake", kind: "task" },
42
+ { name: "Review requirements", kind: "task" },
43
+ { name: "Schedule kickoff", kind: "handoff" },
44
+ ],
45
+ });
46
+ ```
47
+
48
+ The client uses the public API by default. Pass `baseUrl` to use a compatible API origin or
49
+ `fetchImpl` to provide a custom fetch implementation. No account, API key, or payment method is
50
+ required. Results are planning estimates, not forecasts or guaranteed outcomes.
51
+
52
+ To run from a source checkout before publication:
53
+
54
+ ```sh
55
+ npm install --prefix cli
56
+ node cli/bin/shire.js tools
57
+ ```
58
+
59
+ ## Commands
60
+
61
+ ```sh
62
+ shire services
63
+ shire pricing
64
+ shire tools
65
+ shire catalog
66
+ shire plan workflow-mapper --input workflow.json
67
+ cat workflow.json | shire plan workflow-mapper --input -
68
+ ```
69
+
70
+ Planning commands accept JSON and print JSON. The workflow mapper returns an editable SOP draft. Other tools score an automation opportunity, assess AI readiness, plan an integration, build an onboarding checklist, or estimate workload and ROI.
71
+
72
+ Set `SHIRE_API_URL` to an alternate API origin for development. The default is `https://shireautomations.com`.
73
+
74
+ ## MCP server
75
+
76
+ The package also runs a local stdio MCP server:
77
+
78
+ ```sh
79
+ shire mcp
80
+ ```
81
+
82
+ Example client configuration:
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "shireautomations": {
88
+ "command": "shire",
89
+ "args": ["mcp"]
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ The server exposes `shire_catalog`, `shire_list_planning_tools`, and `shire_plan`. It calls the same versioned API as the CLI. It does not ask for API credentials, submit intake forms, or start paid work.
96
+
97
+ ## API and privacy
98
+
99
+ See the [API and developer resources](https://shireautomations.com/developers), [JavaScript SDK guide](https://shireautomations.com/sdk), [OpenAPI specification](https://shireautomations.com/openapi.json), or [Postman collection](https://shireautomations.com/postman-collection.json). The API does not save synchronous planning requests. Do not send credentials or sensitive customer, patient, or financial-account data. Estimates depend on the input values and are not forecasts or guarantees.
100
+
101
+ ## About Shire Automations
102
+
103
+ Shire Automations is a Houston-based business automation and software studio. We connect workflows and build AI agents, apps, and dashboards for small and midsize businesses. Learn more at [shireautomations.com](https://shireautomations.com).
package/bin/shire.js ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile } from "node:fs/promises";
4
+ import { stdin, stdout, stderr } from "node:process";
5
+ import { fetchShireJson } from "../src/client.js";
6
+
7
+ const HELP = `Shire Automations CLI
8
+
9
+ Usage:
10
+ shire catalog
11
+ shire services
12
+ shire pricing
13
+ shire tools
14
+ shire plan <tool> --input <file|->
15
+ shire mcp
16
+
17
+ Planning results are estimates from your inputs. Requests are not saved by the API.
18
+ Set SHIRE_API_URL to use another Shire-compatible API origin.`;
19
+
20
+ function print(value) {
21
+ stdout.write(`${JSON.stringify(value, null, 2)}\n`);
22
+ }
23
+
24
+ async function readStdin() {
25
+ let value = "";
26
+ for await (const chunk of stdin) value += chunk;
27
+ return value;
28
+ }
29
+
30
+ async function readInput(args) {
31
+ const index = args.indexOf("--input");
32
+ if (index === -1 || !args[index + 1]) throw new Error("Pass --input <file|-> with a JSON object.");
33
+ const raw = args[index + 1] === "-" ? await readStdin() : await readFile(args[index + 1], "utf8");
34
+ const value = JSON.parse(raw);
35
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
36
+ throw new Error("The planning input must be a JSON object.");
37
+ }
38
+ return value;
39
+ }
40
+
41
+ async function main() {
42
+ const [command, ...args] = process.argv.slice(2);
43
+
44
+ if (!command || command === "help" || command === "--help" || command === "-h") {
45
+ stdout.write(`${HELP}\n`);
46
+ return;
47
+ }
48
+
49
+ if (command === "mcp") {
50
+ await import("../src/mcp.js");
51
+ return;
52
+ }
53
+
54
+ if (command === "catalog") {
55
+ print(await fetchShireJson("/api/v1/catalog"));
56
+ return;
57
+ }
58
+
59
+ if (command === "services" || command === "pricing") {
60
+ const catalog = await fetchShireJson("/api/v1/catalog");
61
+ print(command === "services" ? catalog.services : { pricing: catalog.pricing, note: catalog.pricingNote });
62
+ return;
63
+ }
64
+
65
+ if (command === "tools") {
66
+ print(await fetchShireJson("/api/v1/tools"));
67
+ return;
68
+ }
69
+
70
+ if (command === "plan") {
71
+ const slug = args[0];
72
+ if (!slug) throw new Error("Pass the planning tool name after plan.");
73
+ const input = await readInput(args.slice(1));
74
+ print(await fetchShireJson(`/api/v1/tools/${encodeURIComponent(slug)}`, {
75
+ method: "POST",
76
+ headers: { "Content-Type": "application/json" },
77
+ body: JSON.stringify({ input }),
78
+ }));
79
+ return;
80
+ }
81
+
82
+ throw new Error(`Unknown command: ${command}\n\n${HELP}`);
83
+ }
84
+
85
+ main().catch((error) => {
86
+ stderr.write(`${error instanceof Error ? error.message : "Shire request failed."}\n`);
87
+ process.exitCode = 1;
88
+ });
package/package.json CHANGED
@@ -1,6 +1,30 @@
1
1
  {
2
2
  "name": "shireautomations",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "license": "UNLICENSED",
5
+ "description": "JavaScript SDK, CLI, and MCP server for the Shire Automations public API, built by a Houston-based business automation studio.",
6
+ "type": "module",
7
+ "engines": { "node": ">=20" },
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.d.ts",
11
+ "import": "./src/index.js"
12
+ }
13
+ },
14
+ "types": "./src/index.d.ts",
15
+ "bin": {
16
+ "shire": "bin/shire.js"
17
+ },
18
+ "files": ["bin", "src", "README.md", "server.json"],
19
+ "keywords": ["shire-automations", "workflow-automation", "business-planning", "sdk", "api-client", "mcp", "cli"],
20
+ "homepage": "https://shireautomations.com/",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/praisondani/shireautomations-cli.git"
24
+ },
25
+ "bugs": { "url": "https://github.com/praisondani/shireautomations-cli/issues" },
26
+ "dependencies": {
27
+ "@modelcontextprotocol/server": "^2.3.1",
28
+ "zod": "^4.6.7"
29
+ }
30
+ }
package/server.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.praisondani/shireautomations-cli",
4
+ "title": "Shire Automations",
5
+ "description": "Read Shire Automations services and published prices, and run stateless workflow planning tools through a local MCP server.",
6
+ "websiteUrl": "https://shireautomations.com/developers",
7
+ "repository": {
8
+ "url": "https://github.com/praisondani/shireautomations-cli",
9
+ "source": "github"
10
+ },
11
+ "version": "0.1.1",
12
+ "packages": [
13
+ {
14
+ "registryType": "npm",
15
+ "registryBaseUrl": "https://registry.npmjs.org",
16
+ "identifier": "shireautomations",
17
+ "version": "0.1.1",
18
+ "runtimeHint": "npx",
19
+ "transport": { "type": "stdio" },
20
+ "packageArguments": [{ "type": "positional", "value": "mcp" }]
21
+ }
22
+ ]
23
+ }
package/src/client.js ADDED
@@ -0,0 +1,9 @@
1
+ import { ShireAutomationsClient } from "./index.js";
2
+
3
+ const client = new ShireAutomationsClient({
4
+ baseUrl: process.env.SHIRE_API_URL || "https://shireautomations.com",
5
+ });
6
+
7
+ export async function fetchShireJson(path, options = {}) {
8
+ return client.request(path, options);
9
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,102 @@
1
+ export interface ShireAutomationsClientOptions {
2
+ /** API origin. Defaults to https://shireautomations.com. */
3
+ baseUrl?: string;
4
+ /** Fetch-compatible implementation. Defaults to the Node.js global fetch. */
5
+ fetchImpl?: typeof fetch;
6
+ /** Request timeout in milliseconds. Defaults to 15000. */
7
+ timeoutMs?: number;
8
+ }
9
+
10
+ export interface ShireService {
11
+ name: string;
12
+ path: string;
13
+ url: string;
14
+ }
15
+
16
+ export interface ShirePrice {
17
+ id: string;
18
+ title: string;
19
+ priceLabel: string;
20
+ scope: string;
21
+ description: string;
22
+ price?: number;
23
+ minPrice?: number;
24
+ maxPrice?: number;
25
+ unitText?: string;
26
+ }
27
+
28
+ export interface ShireCatalog {
29
+ name: string;
30
+ description: string;
31
+ version: string;
32
+ website: string;
33
+ developerResources: string;
34
+ contact: string;
35
+ services: ShireService[];
36
+ pricing: ShirePrice[];
37
+ pricingNote: string;
38
+ planningTools: ShirePlanningTool[];
39
+ [key: string]: unknown;
40
+ }
41
+
42
+ export interface ShirePlanningTool {
43
+ id: string;
44
+ name: string;
45
+ description: string;
46
+ path: string;
47
+ endpoint: string;
48
+ method: "POST";
49
+ }
50
+
51
+ export interface ShireToolList {
52
+ version: "1";
53
+ tools: ShirePlanningTool[];
54
+ pagination: {
55
+ limit: number;
56
+ nextCursor: string | null;
57
+ hasMore: boolean;
58
+ };
59
+ openapi: string;
60
+ }
61
+
62
+ export interface ShirePlanningResult {
63
+ version: "1";
64
+ tool: string;
65
+ result: Record<string, unknown>;
66
+ }
67
+
68
+ export interface ShireSandboxInfo {
69
+ mode: "sandbox";
70
+ description: string;
71
+ safeguards: Record<string, string>;
72
+ tools: string[];
73
+ toolsEndpoint: string;
74
+ request: Record<string, unknown>;
75
+ }
76
+
77
+ export interface ShireSandboxResult {
78
+ version: "1";
79
+ mode: "sandbox";
80
+ tool: string;
81
+ result: Record<string, unknown>;
82
+ }
83
+
84
+ export class ShireApiError extends Error {
85
+ status?: number;
86
+ response?: unknown;
87
+ }
88
+
89
+ export class ShireAutomationsClient {
90
+ constructor(options?: ShireAutomationsClientOptions);
91
+ request<T = unknown>(
92
+ path: string,
93
+ options?: { method?: string; headers?: HeadersInit; body?: unknown },
94
+ ): Promise<T>;
95
+ getCatalog(): Promise<ShireCatalog>;
96
+ getServices(): Promise<ShireService[]>;
97
+ getPricing(): Promise<{ pricing: ShirePrice[]; note: string }>;
98
+ listTools(): Promise<ShireToolList>;
99
+ getSandboxInfo(): Promise<ShireSandboxInfo>;
100
+ plan(toolId: string, input: Record<string, unknown>): Promise<ShirePlanningResult>;
101
+ runSandbox(toolId: string, input: Record<string, unknown>): Promise<ShireSandboxResult>;
102
+ }
package/src/index.js ADDED
@@ -0,0 +1,127 @@
1
+ const DEFAULT_API_URL = "https://shireautomations.com";
2
+ const DEFAULT_TIMEOUT_MS = 15_000;
3
+
4
+ export class ShireApiError extends Error {
5
+ constructor(message, { status, response } = {}) {
6
+ super(message);
7
+ this.name = "ShireApiError";
8
+ this.status = status;
9
+ this.response = response;
10
+ }
11
+ }
12
+
13
+ export class ShireAutomationsClient {
14
+ #apiUrl;
15
+ #fetch;
16
+ #timeoutMs;
17
+
18
+ constructor({ baseUrl = DEFAULT_API_URL, fetchImpl = globalThis.fetch, timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {
19
+ let url;
20
+ try {
21
+ url = new URL(baseUrl);
22
+ } catch {
23
+ throw new TypeError("baseUrl must be a valid HTTP or HTTPS URL.");
24
+ }
25
+
26
+ if (!["http:", "https:"].includes(url.protocol) || url.username || url.password) {
27
+ throw new TypeError("baseUrl must use HTTP or HTTPS and cannot include credentials.");
28
+ }
29
+ if (typeof fetchImpl !== "function") {
30
+ throw new TypeError("fetchImpl must be a fetch-compatible function.");
31
+ }
32
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 1) {
33
+ throw new TypeError("timeoutMs must be a positive integer.");
34
+ }
35
+
36
+ this.#apiUrl = url.origin;
37
+ this.#fetch = fetchImpl;
38
+ this.#timeoutMs = timeoutMs;
39
+ }
40
+
41
+ async request(path, { method = "GET", headers, body } = {}) {
42
+ let url;
43
+ try {
44
+ url = new URL(path, this.#apiUrl);
45
+ } catch {
46
+ throw new TypeError("path must be a valid URL path.");
47
+ }
48
+ if (url.origin !== this.#apiUrl) {
49
+ throw new TypeError("path must resolve to the configured API origin.");
50
+ }
51
+
52
+ const requestHeaders = new Headers(headers);
53
+ let requestBody = body;
54
+ if (body !== undefined && typeof body !== "string") {
55
+ requestBody = JSON.stringify(body);
56
+ if (!requestHeaders.has("content-type")) {
57
+ requestHeaders.set("content-type", "application/json");
58
+ }
59
+ }
60
+
61
+ const response = await this.#fetch(url, {
62
+ method,
63
+ headers: requestHeaders,
64
+ ...(requestBody === undefined ? {} : { body: requestBody }),
65
+ signal: AbortSignal.timeout(this.#timeoutMs),
66
+ });
67
+
68
+ let payload;
69
+ try {
70
+ payload = await response.json();
71
+ } catch {
72
+ throw new ShireApiError(`Shire API returned invalid JSON (HTTP ${response.status}).`, {
73
+ status: response.status,
74
+ });
75
+ }
76
+
77
+ if (!response.ok) {
78
+ const message = typeof payload?.error === "string"
79
+ ? payload.error
80
+ : `Shire API request failed (HTTP ${response.status}).`;
81
+ throw new ShireApiError(message, { status: response.status, response: payload });
82
+ }
83
+
84
+ return payload;
85
+ }
86
+
87
+ getCatalog() {
88
+ return this.request("/api/v1/catalog");
89
+ }
90
+
91
+ async getServices() {
92
+ const catalog = await this.getCatalog();
93
+ return catalog.services;
94
+ }
95
+
96
+ async getPricing() {
97
+ const catalog = await this.getCatalog();
98
+ return { pricing: catalog.pricing, note: catalog.pricingNote };
99
+ }
100
+
101
+ listTools() {
102
+ return this.request("/api/v1/tools");
103
+ }
104
+
105
+ getSandboxInfo() {
106
+ return this.request("/api/v1/sandbox");
107
+ }
108
+
109
+ plan(toolId, input) {
110
+ return this.#runTool(`/api/v1/tools/${encodeURIComponent(toolId)}`, toolId, input);
111
+ }
112
+
113
+ runSandbox(toolId, input) {
114
+ return this.#runTool(`/api/v1/sandbox/tools/${encodeURIComponent(toolId)}`, toolId, input);
115
+ }
116
+
117
+ #runTool(path, toolId, input) {
118
+ if (typeof toolId !== "string" || !toolId.trim()) {
119
+ throw new TypeError("toolId must be a non-empty string.");
120
+ }
121
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
122
+ throw new TypeError("input must be a JSON object.");
123
+ }
124
+
125
+ return this.request(path, { method: "POST", body: { input } });
126
+ }
127
+ }
package/src/mcp.js ADDED
@@ -0,0 +1,55 @@
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
+ import { serveStdio } from "@modelcontextprotocol/server/stdio";
3
+ import * as z from "zod/v4";
4
+ import { fetchShireJson } from "./client.js";
5
+
6
+ const planningToolIds = [
7
+ "automation-opportunity-scorecard",
8
+ "workflow-mapper",
9
+ "lead-response-calculator",
10
+ "ai-readiness-assessment",
11
+ "integration-finder",
12
+ "client-onboarding-builder",
13
+ "invoice-follow-up-calculator",
14
+ "roi-calculator",
15
+ ];
16
+
17
+ function createServer() {
18
+ const server = new McpServer({ name: "shireautomations", version: "0.1.1" });
19
+
20
+ server.registerTool("shire_catalog", {
21
+ description: "Read Shire Automations services, starting prices, and public planning tools. Does not create a quote or start paid work.",
22
+ inputSchema: z.object({}),
23
+ }, async () => {
24
+ const catalog = await fetchShireJson("/api/v1/catalog");
25
+ return { content: [{ type: "text", text: JSON.stringify(catalog, null, 2) }] };
26
+ });
27
+
28
+ server.registerTool("shire_list_planning_tools", {
29
+ description: "List the public Shire Automations workflow planning calculators.",
30
+ inputSchema: z.object({}),
31
+ }, async () => {
32
+ const tools = await fetchShireJson("/api/v1/tools");
33
+ return { content: [{ type: "text", text: JSON.stringify(tools, null, 2) }] };
34
+ });
35
+
36
+ server.registerTool("shire_plan", {
37
+ description: "Run one stateless Shire workflow planning tool using values you provide. Results are estimates, not forecasts. Do not send credentials or sensitive customer, patient, or financial-account data.",
38
+ inputSchema: z.object({
39
+ tool: z.enum(planningToolIds),
40
+ input: z.record(z.string(), z.unknown()),
41
+ }),
42
+ }, async ({ tool, input }) => {
43
+ const result = await fetchShireJson(`/api/v1/tools/${encodeURIComponent(tool)}`, {
44
+ method: "POST",
45
+ headers: { "Content-Type": "application/json" },
46
+ body: JSON.stringify({ input }),
47
+ });
48
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
49
+ });
50
+
51
+ return server;
52
+ }
53
+
54
+ await serveStdio(createServer);
55
+ console.error("Shire Automations MCP server ready on stdio.");