doubleoh-mcp 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/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # doubleoh-mcp
2
+
3
+ **The DoubleOh fix loop as an MCP server.** Any MCP-capable agent — Claude Code, Claude
4
+ Desktop, and the growing list of clients — gets the loop as three tools with zero
5
+ integration code.
6
+
7
+ ```json
8
+ {
9
+ "mcpServers": {
10
+ "doubleoh": {
11
+ "command": "bunx",
12
+ "args": ["doubleoh-mcp"],
13
+ "env": { "DOUBLEOH_API_KEY": "oo_live_…" }
14
+ }
15
+ }
16
+ }
17
+ ```
18
+
19
+ ## The tools
20
+
21
+ - **`doubleoh_skills_for`** — before attempting a task it has failed at before, the agent
22
+ asks what has been learned and receives step-by-step procedures from past human fixes,
23
+ with each one's track record.
24
+ - **`doubleoh_request_fix`** — when stuck, the agent asks for a human. If the fleet
25
+ already knows the wall, the procedure comes back instantly instead and nobody is paged.
26
+ Duplicate walls are answered with "already being fixed, N runs blocked" — an agent in a
27
+ retry loop never spams a team.
28
+ - **`doubleoh_report_skill`** — after following a skill, the agent reports whether it
29
+ worked. Skills that keep failing stop being served.
30
+
31
+ Refusals (a private URL, a quota) come back as readable tool results, not protocol
32
+ errors — the model is told what went wrong in a sentence it can act on.
33
+
34
+ `DOUBLEOH_BASE_URL` points at a self-hosted deployment; it defaults to the hosted service.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ /** The binary: read the environment, speak stdio. Plain Node — no bun required. */
3
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /** The binary: read the environment, speak stdio. Plain Node — no bun required. */
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { DoubleOh } from "@doubleoh/sdk";
5
+ import { createServer } from "./index.js";
6
+ const apiKey = process.env.DOUBLEOH_API_KEY;
7
+ if (!apiKey) {
8
+ console.error("DOUBLEOH_API_KEY is required (it starts with oo_).");
9
+ process.exit(1);
10
+ }
11
+ const client = new DoubleOh({
12
+ apiKey,
13
+ ...(process.env.DOUBLEOH_BASE_URL
14
+ ? { baseUrl: process.env.DOUBLEOH_BASE_URL }
15
+ : {}),
16
+ });
17
+ await createServer(client).connect(new StdioServerTransport());
@@ -0,0 +1,18 @@
1
+ /**
2
+ * doubleoh-mcp — the fix loop as an MCP server.
3
+ *
4
+ * Any MCP-capable agent (Claude Code, Claude Desktop, and the growing list of clients) gets the
5
+ * three tools with zero integration code:
6
+ *
7
+ * { "mcpServers": { "doubleoh": {
8
+ * "command": "bunx", "args": ["doubleoh-mcp"],
9
+ * "env": { "DOUBLEOH_API_KEY": "oo_live_…" } } } }
10
+ *
11
+ * The tools themselves come from @doubleoh/sdk's framework-agnostic definitions — this file is only
12
+ * the MCP shell around them, which is the point: one definition, every framework. The low-level
13
+ * Server API is used on purpose: the definitions already carry JSON Schema, which is what MCP puts
14
+ * on the wire, so translating them through zod would be a round trip to nowhere.
15
+ */
16
+ import { DoubleOh } from "@doubleoh/sdk";
17
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
18
+ export declare function createServer(client: DoubleOh): Server;
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * doubleoh-mcp — the fix loop as an MCP server.
3
+ *
4
+ * Any MCP-capable agent (Claude Code, Claude Desktop, and the growing list of clients) gets the
5
+ * three tools with zero integration code:
6
+ *
7
+ * { "mcpServers": { "doubleoh": {
8
+ * "command": "bunx", "args": ["doubleoh-mcp"],
9
+ * "env": { "DOUBLEOH_API_KEY": "oo_live_…" } } } }
10
+ *
11
+ * The tools themselves come from @doubleoh/sdk's framework-agnostic definitions — this file is only
12
+ * the MCP shell around them, which is the point: one definition, every framework. The low-level
13
+ * Server API is used on purpose: the definitions already carry JSON Schema, which is what MCP puts
14
+ * on the wire, so translating them through zod would be a round trip to nowhere.
15
+ */
16
+ import { DoubleOhError } from "@doubleoh/sdk";
17
+ import { doubleohTools } from "@doubleoh/sdk/tools";
18
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
19
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
20
+ export function createServer(client) {
21
+ const tools = doubleohTools(client);
22
+ const server = new Server({ name: "doubleoh", version: "0.1.0" }, { capabilities: { tools: {} } });
23
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
24
+ tools: tools.map((tool) => ({
25
+ name: tool.name,
26
+ description: tool.description,
27
+ inputSchema: tool.parameters,
28
+ })),
29
+ }));
30
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
31
+ const tool = tools.find((candidate) => candidate.name === request.params.name);
32
+ if (!tool) {
33
+ return {
34
+ content: [
35
+ { type: "text", text: `No tool named ${request.params.name}.` },
36
+ ],
37
+ isError: true,
38
+ };
39
+ }
40
+ try {
41
+ const text = await tool.execute(request.params.arguments ?? {});
42
+ return { content: [{ type: "text", text }] };
43
+ }
44
+ catch (error) {
45
+ /*
46
+ * A refusal is an answer the model should read, not a protocol failure: "that address is not
47
+ * reachable for a fix" tells the agent to stop aiming at intranet hosts.
48
+ */
49
+ const text = error instanceof DoubleOhError
50
+ ? `DoubleOh refused (${error.status}): ${error.message}`
51
+ : `DoubleOh was unreachable: ${String(error)}`;
52
+ return { content: [{ type: "text", text }], isError: true };
53
+ }
54
+ });
55
+ return server;
56
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "doubleoh-mcp",
3
+ "version": "0.1.0",
4
+ "description": "The DoubleOh fix loop as an MCP server: skills_for, request_fix, report_skill.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "doubleoh-mcp": "./dist/cli.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "^1.12.0",
13
+ "@doubleoh/sdk": "0.1.0"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -p tsconfig.build.json",
17
+ "typecheck": "tsc --noEmit"
18
+ },
19
+ "devDependencies": {
20
+ "bun-types": "^1.4.0"
21
+ },
22
+ "types": "./dist/index.d.ts",
23
+ "files": [
24
+ "dist",
25
+ "README.md"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ }
30
+ }