Skill: swgoettelman/deal-works-mcp (version 0.1.0)

--- name: deal-works description: AI agent infrastructure for deals, escrow, attestations, and autonomous agents. 39 tools across 9 engines. version: 0.1.0 author: swgoettelman license: MIT metadata: openclaw: emoji: "🤝" homepage: https://deal.works primaryEnv: DEAL_WORKS_API_KEY requires: env: - DEAL_WORKS_API_KEY bins: - node install: - kind: node package: "@swgoettelman/deal-works-mcp" bins: [deal-works-mcp] mcp: server: "@swgoettelman/deal-works-mcp" transport: stdio tags: - deals - escrow - smart-contracts - attestation - agents - blockchain - finance - mcp --- # deal.works AI agent infrastructure for trustworthy deal-making. Enables agents to create deals, manage escrow, deploy autonomous agents, and issue cryptographic attestations. ## Quick Start ```bash # Install the skill openclaw skill add swgoettelman/deal-works # Set your API key export DEAL_WORKS_API_KEY=your_key_here # The skill is now available to your agent ``` Get your API key at [hq.works/settings/api](https://hq.works/settings/api). ## Capabilities ### 9 Engines, 39 Tools | Engine | Tools | Purpose | |--------|-------|---------| | **Deal** | 7 | Deal lifecycle: create, sign, approve, search, timeline | | **Fund** | 6 | Wallets, transfers, escrow, cashout, agent funding | | **Bourse** | 5 | Marketplace for templates, skills, integrations | | **Cadre** | 6 | Deploy and manage autonomous agents | | **Oath** | 5 | Cryptographic attestations (completed on-chain) | | **Parler** | 4 | Dispute resolution and governance | | **Academy** | 3 | Learning platform for deal-making | | **HQ** | 2 | Dashboard metrics and system health | | **Clause** | 1 | Contract clause rendering | ### 7 Resources - `dealworks://profile` - User profile and trust tier - `dealworks://wallet` - Wallet balances - `dealworks://deals` - Active deals - `dealworks://agents` - Deployed agents - `dealworks://templates` - Available templates - `dealworks://disputes` - Open disputes - `dealworks://dashboard` - Key metrics ### 5 Pre-built Prompts - `escrow-deal` - Create escrow-protected deal workflow - `deploy-agent` - Deploy agent from skill - `file-dispute` - File dispute with evidence - `publish-template` - Publish template to Bourse - `portfolio-review` - Review deal portfolio ## Common Workflows ### Create an Escrow Deal ``` User: Create a $5000 escrow deal with [REDACTED_SECRET] for website development Agent: I'll use deal_create to create the deal, then fund_escrow to lock the funds, and oath_attest to prepare completion verification. ``` ### Deploy a Monitoring Agent ``` User: Deploy an agent to monitor my active deals and alert on SLA violations Agent: I'll use bourse_search to find monitoring skills, cadre_deploy to launch the agent, and fund_agent_fund to allocate operational budget. ``` ### File a Dispute ``` User: The contractor didn't deliver. File a dispute for deal xyz123. Agent: I'll use deal_get to review the deal, then parler_dispute_file with the evidence. The dispute enters the resolution queue. ``` ## Tool Reference ### Deal Engine | Tool | Description | |------|-------------| | `deal_list` | List deals with optional status filter | | `deal_create` | Create a new deal with terms and counterparty | | `deal_get` | Get detailed deal information | | `deal_action` | Perform action: SIGN, APPROVE, REJECT, CANCEL, COMPLETE, ARCHIVE | | `deal_search` | Search deals by text query | | `deal_timeline` | Get activity timeline for a deal | | `deal_attachments` | List deal attachments | ### Fund Engine | Tool | Description | |------|-------------| | `fund_balance` | Get wallet balance (available, locked, pending) | | `fund_transfer` | Transfer funds between wallets | | `fund_transactions` | List transaction history | | `fund_escrow` | Lock funds in escrow for a deal | | `fund_cashout` | Cash out to external wallet on Base | | `fund_agent_fund` | Fund an agent's operational wallet | ### Bourse Engine | Tool | Description | |------|-------------| | `bourse_search` | Search marketplace for templates/skills | | `bourse_get` | Get listing details and reviews | | `bourse_fork` | Fork a listing to customize | | `bourse_publish` | Publish to marketplace | | `bourse_earnings` | View earnings from published listings | ### Cadre Engine | Tool | Description | |------|-------------| | `cadre_list` | List deployed agents | | `cadre_deploy` | Deploy a new agent from skill | | `cadre_command` | Send command: START, STOP, RESTART, SCALE | | `cadre_health` | Get agent health status | | `cadre_delegations` | List permission delegations | | `cadre_sla_violations` | List SLA violations | ### Oath Engine | Tool | Description | |------|-------------| | `oath_attest` | Create attestation for deal milestone | | `oath_verify` | Verify attestation authenticity | | `oath_vault_upload` | Upload document hashes to vault | | `oath_vault_seal` | Seal vault with Merkle root on-chain | | `oath_trust_tier` | Get user/org trust tier | ### Parler Engine | Tool | Description | |------|-------------| | `parler_dispute_file` | File a dispute with evidence | | `parler_dispute_list` | List disputes by status/role | | `parler_proposals` | List resolution proposals | | `parler_vote` | Vote on proposal | ### Academy Engine | Tool | Description | |------|-------------| | `academy_courses` | Browse available courses | | `academy_enroll` | Enroll in a course | | `academy_tip` | Tip a course creator | ### HQ Engine | Tool | Description | |------|-------------| | `hq_dashboard` | Get dashboard metrics | | `hq_health` | Check system health | ### Clause Engine | Tool | Description | |------|-------------| | `clause_render` | Render contract clause template | ## Security - All mutations use idempotency keys (safe to retry) - API keys scoped per engine - Rate limited: 100 requests/minute - Circuit breaker per engine (5 failures = 30s cooldown) - Only calls *.works domains + approved external APIs ## Links - [deal.works](https://deal.works) - Main platform - [Documentation](https://docs.deal.works) - Full API docs - [npm package](https://www.npmjs.com/package/@swgoettelman/deal-works-mcp) - [GitHub](https://github.com/swgoettelman/titanium-federation)

path: README.md
content: # @swgoettelman/deal-works-mcp

MCP (Model Context Protocol) server exposing the deal.works platform to AI agents. Provides 39 tools across 9 engines for deal management, escrow, agent deployment, attestations, and more.

## Installation

```bash
npx @swgoettelman/deal-works-mcp
```

Or install globally:

```bash
npm install -g @swgoettelman/deal-works-mcp
```

## Configuration

### Environment Variables

```bash
export DEAL_WORKS_API_KEY=your_api_key_here
```

Get your API key from [hq.works/settings/api](https://hq.works/settings/api).

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "deal-works": {
      "command": "npx",
      "args": ["@goettelman/deal-works-mcp"],
      "env": {
        "DEAL_WORKS_API_KEY": "your_api_key_here"
      }
    }
  }
}
```

### Cursor / VS Code

Add to your MCP configuration:

```json
{
  "deal-works": {
    "command": "npx",
    "args": ["@goettelman/deal-works-mcp"],
    "env": {
      "DEAL_WORKS_API_KEY": "your_api_key_here"
    }
  }
}
```

### OpenClaw

```bash
openclaw skill add goettelman/deal-works
```

## Tools (39 total)

### Deal Engine (7 tools)
- `deal_list` - List deals with status filter
- `deal_create` - Create a new deal
- `deal_get` - Get deal details
- `deal_action` - Perform deal actions (sign, approve, reject, etc.)
- `deal_search` - Search deals by query
- `deal_timeline` - Get deal activity timeline
- `deal_attachments` - List deal attachments

### Fund Engine (6 tools)
- `fund_balance` - Get wallet balance
- `fund_transfer` - Transfer funds between wallets
- `fund_transactions` - List transaction history
- `fund_escrow` - Lock funds in escrow for a deal
- `fund_cashout` - Cash out to external wallet
- `fund_agent_fund` - Fund an agent's operational wallet

### Bourse Engine (5 tools)
- `bourse_search` - Search marketplace for templates/skills
- `bourse_get` - Get listing details
- `bourse_fork` - Fork a listing
- `bourse_publish` - Publish to marketplace
- `bourse_earnings` - View earnings from published listings

### Cadre Engine (6 tools)
- `cadre_list` - List deployed agents
- `cadre_deploy` - Deploy a new agent
- `cadre_command` - Send command to agent (start/stop/restart)
- `cadre_health` - Get agent health status
- `cadre_delegations` - List permission delegations
- `cadre_sla_violations` - List SLA violations

### Oath Engine (5 tools)
- `oath_attest` - Create attestation for a deal
- `oath_verify` - Verify attestation authenticity
- `oath_vault_upload` - Upload documents to secure vault
- `oath_vault_seal` - Seal vault with Merkle root
- `oath_trust_tier` - Get user/org trust tier

### Parler Engine (4 tools)
- `parler_dispute_file` - File a dispute
- `parler_dispute_list` - List disputes
- `parler_proposals` - List resolution proposals
- `parler_vote` - Vote on proposals

### Academy Engine (3 tools)
- `academy_courses` - Browse courses
- `academy_enroll` - Enroll in a course
- `academy_tip` - Tip a course creator

### HQ Engine (2 tools)
- `hq_dashboard` - Get dashboard metrics
- `hq_health` - Check system health

### Clause Engine (1 tool)
- `clause_render` - Render contract clause template

## Resources (7 total)

- `dealworks://profile` - User profile and trust tier
- `dealworks://wallet` - Wallet balances
- `dealworks://deals` - Active deals
- `dealworks://agents` - Deployed agents
- `dealworks://templates` - Available templates
- `dealworks://disputes` - Open disputes
- `dealworks://dashboard` - Key metrics

## Prompts (5 total)

- `escrow-deal` - Create escrow-protected deal workflow
- `deploy-agent` - Deploy agent from skill
- `file-dispute` - File dispute with evidence
- `publish-template` - Publish template to Bourse
- `portfolio-review` - Review deal portfolio

## Example Usage

### Create an Escrow Deal

```
User: Create a $5000 escrow deal with [REDACTED_SECRET] for website development

Claude: I'll help you create an escrow-protected deal. Let me:
1. Create the deal
2. Set up escrow
3. Prepare attestation for completion
```

### Deploy an Agent

```
User: Deploy a monitoring agent with a $100 budget

Claude: I'll search for monitoring skills and deploy an agent:
1. Searching Bourse for monitoring skills...
2. Deploying agent with SLA configuration...
3. Funding agent wallet...
```

## Security

- API keys are scoped per engine
- All mutations use idempotency keys
- Rate limited to 100 requests/minute
- Circuit breaker per engine (5 failures = 30s cooldown)
- Only calls *.works domains + approved external APIs

## License

MIT

## Links

- [deal.works](https://deal.works)
- [Documentation](https://docs.deal.works)
- [API Reference](https://docs.deal.works/api)
- [GitHub](https://github.com/goettelman/deal.works)


path: dist/index.d.ts
content: 
export {  }


path: dist/index.js
content: #!/usr/bin/env node

// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListPromptsRequestSchema,
  GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types.js";

// src/engines/deal.ts
import { z } from "zod";

// src/client.ts
var DEFAULT_BASE_URLS = {
  deal: "https://deal.works/api",
  fund: "https://fund.works/api",
  bourse: "https://bourse.works/api",
  cadre: "https://cadre.works/api",
  oath: "https://oath.works/api",
  parler: "https://parler.works/api",
  academy: "https://academy.works/api",
  hq: "https://hq.works/api",
  clause: "https://clause.works/api"
};
var RETRYABLE_STATUS_CODES = [429, 502, 503, 504];
var RETRY_DELAYS = [1e3, 2e3, 4e3];
var circuitState = {};
var CIRCUIT_FAILURE_THRESHOLD = 5;
var CIRCUIT_WINDOW_MS = 6e4;
var CIRCUIT_OPEN_DURATION_MS = 3e4;
function checkCircuit(engine) {
  const state = circuitState[engine];
  if (!state) return;
  const now = Date.now();
  if (state.openUntil > now) {
    throw new Error(`Circuit open for ${engine} engine. Retry after ${Math.ceil((state.openUntil - now) / 1e3)}s`);
  }
  if (now - state.lastFailure > CIRCUIT_WINDOW_MS) {
    state.failures = 0;
  }
}
function recordFailure(engine) {
  if (!circuitState[engine]) {
    circuitState[engine] = { failures: 0, lastFailure: 0, openUntil: 0 };
  }
  const state = circuitState[engine];
  const now = Date.now();
  state.failures++;
  state.lastFailure = now;
  if (state.failures >= CIRCUIT_FAILURE_THRESHOLD) {
    state.openUntil = now + CIRCUIT_OPEN_DURATION_MS;
    state.failures = 0;
  }
}
function recordSuccess(engine) {
  if (circuitState[engine]) {
    circuitState[engine].failures = 0;
  }
}
var EngineClient = class {
  apiKey;
  baseUrls;
  timeout;
  maxRetries;
  constructor(config = {}) {
    this.[REDACTED_SECRET] ?? process.env.DEAL_WORKS_API_KEY;
    this.baseUrls = { ...DEFAULT_BASE_URLS, ...config.baseUrls };
    this.timeout = config.timeout ?? 3e4;
    this.maxRetries = config.maxRetries ?? 3;
  }
  async fetch(engine, path, options = {}) {
    const { method = "GET", body, idempotencyKey } = options;
    checkCircuit(engine);
    const baseUrl = this.baseUrls[engine];
    if (!baseUrl) {
      return {
        success: false,
        error: {
          code: "UNKNOWN_ENGINE",
          message: `Unknown engine: ${engine}`,
          retryable: false
        }
      };
    }
    const url = `${baseUrl}${path}`;
    const headers = {
      "Content-Type": "application/json",
      "User-Agent": "@goettelman/deal-works-mcp/0.1.0"
    };
    if (this.apiKey) {
      headers["Authorization"] = `Bearer ${this.apiKey}`;
    }
    if (idempotencyKey) {
      headers["X-Idempotency-Key"] = idempotencyKey;
    }
    let lastError = null;
    for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
      try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), this.timeout);
        const response = await fetch(url, {
          method,
          headers,
          body: body ? JSON.stringify(body) : void 0,
          signal: controller.signal
        });
        clearTimeout(timeoutId);
        if (response.ok) {
          recordSuccess(engine);
          const data = await response.json();
          return { success: true, data };
        }
        const isRetryable = RETRYABLE_STATUS_CODES.includes(response.status);
        if (!isRetryable || attempt === this.maxRetries) {
          recordFailure(engine);
          const errorBody = await response.text();
          return {
            success: false,
            error: {
              code: `HTTP_${response.status}`,
              message: errorBody || response.statusText,
              retryable: isRetryable
            }
          };
        }
        await sleep(RETRY_DELAYS[attempt] ?? 4e3);
      } catch (err) {
        lastError = err instanceof Error ? err : new Error(String(err));
        if (attempt === this.maxRetries) {
          recordFailure(engine);
          return {
            success: false,
            error: {
              code: "NETWORK_ERROR",
              message: lastError.message,
              retryable: true
            }
          };
        }
        await sleep(RETRY_DELAYS[attempt] ?? 4e3);
      }
    }
    return {
      success: false,
      error: {
        code: "MAX_RETRIES_EXCEEDED",
        message: lastError?.message ?? "Max retries exceeded",
        retryable: false
      }
    };
  }
};
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}
var clientInstance = null;
function getEngineClient(config) {
  if (!clientInstance || config) {
    clientInstance = new EngineClient(config);
  }
  return clientInstance;
}

// src/engines/deal.ts
var DealListInputSchema = z.object({
  status: z.enum(["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"]).optional(),
  limit: z.number().min(1).max(100).default(20),
  offset: z.number().min(0).default(0)
});
var DealCreateInputSchema = z.object({
  title: z.string().min(1).max(200),
  description: z.string().max(5e3).optional(),
  counterpartyEmail: z.string().email().optional(),
  templateId: z.string().optional(),
  amount: z.number().positive().optional(),
  currency: z.string().default("USD"),
  dueDate: z.string().datetime().optional()
});
var DealGetInputSchema = z.object({
  dealId: z.string().min(1)
});
var DealActionInputSchema = z.object({
  dealId: z.string().min(1),
  action: z.enum(["SIGN", "APPROVE", "REJECT", "CANCEL", "COMPLETE", "ARCHIVE"]),
  comment: z.string().max(1e3).optional()
});
var DealSearchInputSchema = z.object({
  query: z.string().min(1).max(200),
  status: z.enum(["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"]).optional(),
  fromDate: z.string().datetime().optional(),
  toDate: z.string().datetime().optional(),
  limit: z.number().min(1).max(100).default(20)
});
var DealTimelineInputSchema = z.object({
  dealId: z.string().min(1),
  limit: z.number().min(1).max(100).default(50)
});
var DealAttachmentsInputSchema = z.object({
  dealId: z.string().min(1)
});
var dealTools = [
  {
    name: "deal_list",
    description: "List deals with optional status filter. Returns paginated list of deals for the authenticated user.",
    inputSchema: {
      type: "object",
      properties: {
        status: {
          type: "string",
          enum: ["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"],
          description: "Filter by deal status"
        },
        limit: {
          type: "number",
          description: "Number of deals to return (max 100)",
          default: 20
        },
        offset: {
          type: "number",
          description: "Pagination offset",
          default: 0
        }
      }
    }
  },
  {
    name: "deal_create",
    description: "Create a new deal. Can optionally use a template and specify counterparty.",
    inputSchema: {
      type: "object",
      properties: {
        title: {
          type: "string",
          description: "Deal title (required)"
        },
        description: {
          type: "string",
          description: "Deal description"
        },
        counterpartyEmail: {
          type: "string",
          description: "Email of the counterparty to invite"
        },
        templateId: {
          type: "string",
          description: "Template ID to base the deal on"
        },
        amount: {
          type: "number",
          description: "Deal amount"
        },
        currency: {
          type: "string",
          description: "Currency code (default: USD)"
        },
        dueDate: {
          type: "string",
          description: "Due date in ISO 8601 format"
        }
      },
      required: ["title"]
    }
  },
  {
    name: "deal_get",
    description: "Get detailed information about a specific deal including parties, terms, and current status.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID"
        }
      },
      required: ["dealId"]
    }
  },
  {
    name: "deal_action",
    description: "Perform an action on a deal: sign, approve, reject, cancel, complete, or archive.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID"
        },
        action: {
          type: "string",
          enum: ["SIGN", "APPROVE", "REJECT", "CANCEL", "COMPLETE", "ARCHIVE"],
          description: "Action to perform"
        },
        comment: {
          type: "string",
          description: "Optional comment for the action"
        }
      },
      required: ["dealId", "action"]
    }
  },
  {
    name: "deal_search",
    description: "Search deals by text query across titles, descriptions, and party names.",
    inputSchema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Search query"
        },
        status: {
          type: "string",
          enum: ["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"],
          description: "Filter by status"
        },
        fromDate: {
          type: "string",
          description: "Start date filter (ISO 8601)"
        },
        toDate: {
          type: "string",
          description: "End date filter (ISO 8601)"
        },
        limit: {
          type: "number",
          description: "Max results",
          default: 20
        }
      },
      required: ["query"]
    }
  },
  {
    name: "deal_timeline",
    description: "Get the activity timeline for a deal showing all events and state changes.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID"
        },
        limit: {
          type: "number",
          description: "Max events to return",
          default: 50
        }
      },
      required: ["dealId"]
    }
  },
  {
    name: "deal_attachments",
    description: "List all attachments (documents, files) associated with a deal.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID"
        }
      },
      required: ["dealId"]
    }
  }
];
async function handleDealTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "deal_list": {
      const input = DealListInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.status) params.set("status", input.status);
      params.set("limit", String(input.limit));
      params.set("offset", String(input.offset));
      return client.fetch("deal", `/deals?${params.toString()}`);
    }
    case "deal_create": {
      const input = DealCreateInputSchema.parse(args);
      return client.fetch("deal", "/deals", {
        method: "POST",
        body: input,
        idempotencyKey: `create-${Date.now()}`
      });
    }
    case "deal_get": {
      const input = DealGetInputSchema.parse(args);
      return client.fetch("deal", `/deals/${input.dealId}`);
    }
    case "deal_action": {
      const input = DealActionInputSchema.parse(args);
      return client.fetch("deal", `/deals/${input.dealId}/actions`, {
        method: "POST",
        body: { action: input.action, comment: input.comment },
        idempotencyKey: `action-${input.dealId}-${input.action}-${Date.now()}`
      });
    }
    case "deal_search": {
      const input = DealSearchInputSchema.parse(args);
      return client.fetch("deal", "/deals/search", {
        method: "POST",
        body: input
      });
    }
    case "deal_timeline": {
      const input = DealTimelineInputSchema.parse(args);
      const params = new URLSearchParams({ limit: String(input.limit) });
      return client.fetch("deal", `/deals/${input.dealId}/timeline?${params.toString()}`);
    }
    case "deal_attachments": {
      const input = DealAttachmentsInputSchema.parse(args);
      return client.fetch("deal", `/deals/${input.dealId}/attachments`);
    }
    default:
      throw new Error(`Unknown deal tool: ${name}`);
  }
}

// src/engines/fund.ts
import { z as z2 } from "zod";
var FundBalanceInputSchema = z2.object({
  walletId: z2.string().optional()
});
var FundTransferInputSchema = z2.object({
  toWalletId: z2.string().min(1),
  amount: z2.number().positive(),
  currency: z2.string().default("TALER"),
  memo: z2.string().max(500).optional(),
  idempotencyKey: z2.string().optional()
});
var FundTransactionsInputSchema = z2.object({
  walletId: z2.string().optional(),
  type: z2.enum(["CREDIT", "DEBIT", "ESCROW_LOCK", "ESCROW_RELEASE"]).optional(),
  limit: z2.number().min(1).max(100).default(50),
  offset: z2.number().min(0).default(0)
});
var FundEscrowInputSchema = z2.object({
  dealId: z2.string().min(1),
  amount: z2.number().positive(),
  currency: z2.string().default("TALER"),
  releaseConditions: z2.array(z2.string()).optional()
});
var FundCashoutInputSchema = z2.object({
  amount: z2.number().positive(),
  destinationAddress: z2.string().min(1),
  network: z2.enum(["BASE", "BASE_SEPOLIA"]).default("BASE_SEPOLIA")
});
var FundAgentFundInputSchema = z2.object({
  agentId: z2.string().min(1),
  amount: z2.number().positive(),
  purpose: z2.string().max(200).optional()
});
var fundTools = [
  {
    name: "fund_balance",
    description: "Get wallet balance including available, locked (in escrow), and pending amounts.",
    inputSchema: {
      type: "object",
      properties: {
        walletId: {
          type: "string",
          description: "Wallet ID (optional, defaults to user's primary wallet)"
        }
      }
    }
  },
  {
    name: "fund_transfer",
    description: "Transfer funds between wallets. Supports Taler tokens on Base.",
    inputSchema: {
      type: "object",
      properties: {
        toWalletId: {
          type: "string",
          description: "Destination wallet ID"
        },
        amount: {
          type: "number",
          description: "Amount to transfer"
        },
        currency: {
          type: "string",
          description: "Currency (default: TALER)"
        },
        memo: {
          type: "string",
          description: "Transfer memo/note"
        },
        idempotencyKey: {
          type: "string",
          description: "Idempotency key to prevent duplicate transfers"
        }
      },
      required: ["toWalletId", "amount"]
    }
  },
  {
    name: "fund_transactions",
    description: "List transaction history with optional type filter.",
    inputSchema: {
      type: "object",
      properties: {
        walletId: {
          type: "string",
          description: "Wallet ID (optional)"
        },
        type: {
          type: "string",
          enum: ["CREDIT", "DEBIT", "ESCROW_LOCK", "ESCROW_RELEASE"],
          description: "Filter by transaction type"
        },
        limit: {
          type: "number",
          description: "Max transactions to return",
          default: 50
        },
        offset: {
          type: "number",
          description: "Pagination offset",
          default: 0
        }
      }
    }
  },
  {
    name: "fund_escrow",
    description: "Lock funds in escrow for a deal. Funds are released when deal conditions are met.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID to escrow funds for"
        },
        amount: {
          type: "number",
          description: "Amount to lock"
        },
        currency: {
          type: "string",
          description: "Currency (default: TALER)"
        },
        releaseConditions: {
          type: "array",
          items: { type: "string" },
          description: "Conditions that must be met to release funds"
        }
      },
      required: ["dealId", "amount"]
    }
  },
  {
    name: "fund_cashout",
    description: "Cash out Taler tokens to external wallet address on Base network.",
    inputSchema: {
      type: "object",
      properties: {
        amount: {
          type: "number",
          description: "Amount to cash out"
        },
        destinationAddress: {
          type: "string",
          description: "Destination wallet address (0x...)"
        },
        network: {
          type: "string",
          enum: ["BASE", "BASE_SEPOLIA"],
          description: "Network (default: BASE_SEPOLIA for testnet)"
        }
      },
      required: ["amount", "destinationAddress"]
    }
  },
  {
    name: "fund_agent_fund",
    description: "Fund an agent's operational wallet for autonomous transactions.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Agent ID to fund"
        },
        amount: {
          type: "number",
          description: "Amount to allocate"
        },
        purpose: {
          type: "string",
          description: "Purpose/reason for funding"
        }
      },
      required: ["agentId", "amount"]
    }
  }
];
async function handleFundTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "fund_balance": {
      const input = FundBalanceInputSchema.parse(args);
      const path = input.walletId ? `/wallets/${input.walletId}/balance` : "/wallets/me/balance";
      return client.fetch("fund", path);
    }
    case "fund_transfer": {
      const input = FundTransferInputSchema.parse(args);
      return client.fetch("fund", "/transfers", {
        method: "POST",
        body: input,
        idempotencyKey: input.idempotencyKey ?? `transfer-${Date.now()}`
      });
    }
    case "fund_transactions": {
      const input = FundTransactionsInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.walletId) params.set("walletId", input.walletId);
      if (input.type) params.set("type", input.type);
      params.set("limit", String(input.limit));
      params.set("offset", String(input.offset));
      return client.fetch("fund", `/transactions?${params.toString()}`);
    }
    case "fund_escrow": {
      const input = FundEscrowInputSchema.parse(args);
      return client.fetch("fund", "/escrow", {
        method: "POST",
        body: input,
        idempotencyKey: `escrow-${input.dealId}-${Date.now()}`
      });
    }
    case "fund_cashout": {
      const input = FundCashoutInputSchema.parse(args);
      return client.fetch("fund", "/cashout", {
        method: "POST",
        body: input,
        idempotencyKey: `cashout-${Date.now()}`
      });
    }
    case "fund_agent_fund": {
      const input = FundAgentFundInputSchema.parse(args);
      return client.fetch("fund", `/agents/${input.agentId}/fund`, {
        method: "POST",
        body: { amount: input.amount, purpose: input.purpose },
        idempotencyKey: `agent-fund-${input.agentId}-${Date.now()}`
      });
    }
    default:
      throw new Error(`Unknown fund tool: ${name}`);
  }
}

// src/engines/bourse.ts
import { z as z3 } from "zod";
var BourseSearchInputSchema = z3.object({
  query: z3.string().min(1).max(200),
  category: z3.enum(["TEMPLATE", "SKILL", "INTEGRATION", "CONNECTOR"]).optional(),
  minQuality: z3.number().min(0).max(100).optional(),
  source: z3.enum(["OFFICIAL", "COMMUNITY", "ACTIVEPIECES"]).optional(),
  limit: z3.number().min(1).max(100).default(20)
});
var BourseGetInputSchema = z3.object({
  listingId: z3.string().min(1)
});
var BourseForkInputSchema = z3.object({
  listingId: z3.string().min(1),
  newName: z3.string().min(1).max(100).optional()
});
var BoursePublishInputSchema = z3.object({
  type: z3.enum(["TEMPLATE", "SKILL", "INTEGRATION"]),
  name: z3.string().min(1).max(100),
  description: z3.string().max(2e3),
  content: z3.record(z3.unknown()),
  price: z3.number().min(0).default(0),
  tags: z3.array(z3.string()).default([])
});
var BourseEarningsInputSchema = z3.object({
  period: z3.enum(["DAY", "WEEK", "MONTH", "ALL"]).default("MONTH")
});
var bourseTools = [
  {
    name: "bourse_search",
    description: "Search the Bourse marketplace for templates, skills, and integrations.",
    inputSchema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Search query"
        },
        category: {
          type: "string",
          enum: ["TEMPLATE", "SKILL", "INTEGRATION", "CONNECTOR"],
          description: "Filter by category"
        },
        minQuality: {
          type: "number",
          description: "Minimum quality score (0-100)"
        },
        source: {
          type: "string",
          enum: ["OFFICIAL", "COMMUNITY", "ACTIVEPIECES"],
          description: "Filter by source"
        },
        limit: {
          type: "number",
          description: "Max results",
          default: 20
        }
      },
      required: ["query"]
    }
  },
  {
    name: "bourse_get",
    description: "Get detailed information about a Bourse listing including reviews and usage stats.",
    inputSchema: {
      type: "object",
      properties: {
        listingId: {
          type: "string",
          description: "Listing ID"
        }
      },
      required: ["listingId"]
    }
  },
  {
    name: "bourse_fork",
    description: "Fork a Bourse listing to create your own customized version.",
    inputSchema: {
      type: "object",
      properties: {
        listingId: {
          type: "string",
          description: "Listing ID to fork"
        },
        newName: {
          type: "string",
          description: "Name for your forked version"
        }
      },
      required: ["listingId"]
    }
  },
  {
    name: "bourse_publish",
    description: "Publish a new template, skill, or integration to the Bourse marketplace.",
    inputSchema: {
      type: "object",
      properties: {
        type: {
          type: "string",
          enum: ["TEMPLATE", "SKILL", "INTEGRATION"],
          description: "Listing type"
        },
        name: {
          type: "string",
          description: "Listing name"
        },
        description: {
          type: "string",
          description: "Description"
        },
        content: {
          type: "object",
          description: "Listing content/definition"
        },
        price: {
          type: "number",
          description: "Price in Talers (0 for free)",
          default: 0
        },
        tags: {
          type: "array",
          items: { type: "string" },
          description: "Tags for discoverability"
        }
      },
      required: ["type", "name", "description", "content"]
    }
  },
  {
    name: "bourse_earnings",
    description: "View your Bourse earnings from published listings.",
    inputSchema: {
      type: "object",
      properties: {
        period: {
          type: "string",
          enum: ["DAY", "WEEK", "MONTH", "ALL"],
          description: "Time period",
          default: "MONTH"
        }
      }
    }
  }
];
async function handleBourseTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "bourse_search": {
      const input = BourseSearchInputSchema.parse(args);
      return client.fetch("bourse", "/listings/search", {
        method: "POST",
        body: input
      });
    }
    case "bourse_get": {
      const input = BourseGetInputSchema.parse(args);
      return client.fetch("bourse", `/listings/${input.listingId}`);
    }
    case "bourse_fork": {
      const input = BourseForkInputSchema.parse(args);
      return client.fetch("bourse", `/listings/${input.listingId}/fork`, {
        method: "POST",
        body: { newName: input.newName },
        idempotencyKey: `fork-${input.listingId}-${Date.now()}`
      });
    }
    case "bourse_publish": {
      const input = BoursePublishInputSchema.parse(args);
      return client.fetch("bourse", "/listings", {
        method: "POST",
        body: input,
        idempotencyKey: `publish-${Date.now()}`
      });
    }
    case "bourse_earnings": {
      const input = BourseEarningsInputSchema.parse(args);
      return client.fetch("bourse", `/earnings?period=${input.period}`);
    }
    default:
      throw new Error(`Unknown bourse tool: ${name}`);
  }
}

// src/engines/cadre.ts
import { z as z4 } from "zod";
var CadreListInputSchema = z4.object({
  status: z4.enum(["RUNNING", "STOPPED", "FAILED", "PENDING"]).optional(),
  limit: z4.number().min(1).max(100).default(20),
  offset: z4.number().min(0).default(0)
});
var CadreDeployInputSchema = z4.object({
  name: z4.string().min(1).max(100),
  skillId: z4.string().min(1),
  config: z4.record(z4.unknown()).optional(),
  fundingAmount: z4.number().positive().optional(),
  slaConfig: z4.object({
    maxLatencyMs: z4.number().positive().optional(),
    minUptime: z4.number().min(0).max(100).optional()
  }).optional()
});
var CadreCommandInputSchema = z4.object({
  agentId: z4.string().min(1),
  command: z4.enum(["START", "STOP", "RESTART", "SCALE_UP", "SCALE_DOWN"]),
  params: z4.record(z4.unknown()).optional()
});
var CadreHealthInputSchema = z4.object({
  agentId: z4.string().min(1)
});
var CadreDelegationsInputSchema = z4.object({
  agentId: z4.string().optional(),
  status: z4.enum(["ACTIVE", "REVOKED", "EXPIRED"]).optional()
});
var CadreSlaViolationsInputSchema = z4.object({
  agentId: z4.string().optional(),
  severity: z4.enum(["LOW", "MEDIUM", "HIGH", "CRITICAL"]).optional(),
  fromDate: z4.string().datetime().optional(),
  limit: z4.number().min(1).max(100).default(50)
});
var cadreTools = [
  {
    name: "cadre_list",
    description: "List deployed agents with optional status filter.",
    inputSchema: {
      type: "object",
      properties: {
        status: {
          type: "string",
          enum: ["RUNNING", "STOPPED", "FAILED", "PENDING"],
          description: "Filter by agent status"
        },
        limit: {
          type: "number",
          description: "Max agents to return",
          default: 20
        },
        offset: {
          type: "number",
          description: "Pagination offset",
          default: 0
        }
      }
    }
  },
  {
    name: "cadre_deploy",
    description: "Deploy a new agent from a skill definition. Optionally fund and configure SLA.",
    inputSchema: {
      type: "object",
      properties: {
        name: {
          type: "string",
          description: "Agent name"
        },
        skillId: {
          type: "string",
          description: "Skill ID from Bourse to deploy"
        },
        config: {
          type: "object",
          description: "Agent configuration overrides"
        },
        fundingAmount: {
          type: "number",
          description: "Initial funding amount in Talers"
        },
        slaConfig: {
          type: "object",
          properties: {
            maxLatencyMs: { type: "number" },
            minUptime: { type: "number" }
          },
          description: "SLA configuration"
        }
      },
      required: ["name", "skillId"]
    }
  },
  {
    name: "cadre_command",
    description: "Send a command to an agent: start, stop, restart, or scale.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Agent ID"
        },
        command: {
          type: "string",
          enum: ["START", "STOP", "RESTART", "SCALE_UP", "SCALE_DOWN"],
          description: "Command to execute"
        },
        params: {
          type: "object",
          description: "Command parameters (e.g., scale factor)"
        }
      },
      required: ["agentId", "command"]
    }
  },
  {
    name: "cadre_health",
    description: "Get health status and metrics for a specific agent.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Agent ID"
        }
      },
      required: ["agentId"]
    }
  },
  {
    name: "cadre_delegations",
    description: "List permission delegations granted to agents.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Filter by agent ID"
        },
        status: {
          type: "string",
          enum: ["ACTIVE", "REVOKED", "EXPIRED"],
          description: "Filter by delegation status"
        }
      }
    }
  },
  {
    name: "cadre_sla_violations",
    description: "List SLA violations for agents. Used for monitoring and alerting.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Filter by agent ID"
        },
        severity: {
          type: "string",
          enum: ["LOW", "MEDIUM", "HIGH", "CRITICAL"],
          description: "Filter by severity"
        },
        fromDate: {
          type: "string",
          description: "Start date filter (ISO 8601)"
        },
        limit: {
          type: "number",
          description: "Max violations to return",
          default: 50
        }
      }
    }
  }
];
async function handleCadreTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "cadre_list": {
      const input = CadreListInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.status) params.set("status", input.status);
      params.set("limit", String(input.limit));
      params.set("offset", String(input.offset));
      return client.fetch("cadre", `/agents?${params.toString()}`);
    }
    case "cadre_deploy": {
      const input = CadreDeployInputSchema.parse(args);
      return client.fetch("cadre", "/agents", {
        method: "POST",
        body: input,
        idempotencyKey: `deploy-${input.skillId}-${Date.now()}`
      });
    }
    case "cadre_command": {
      const input = CadreCommandInputSchema.parse(args);
      return client.fetch("cadre", `/agents/${input.agentId}/command`, {
        method: "POST",
        body: { command: input.command, params: input.params },
        idempotencyKey: `command-${input.agentId}-${input.command}-${Date.now()}`
      });
    }
    case "cadre_health": {
      const input = CadreHealthInputSchema.parse(args);
      return client.fetch("cadre", `/agents/${input.agentId}/health`);
    }
    case "cadre_delegations": {
      const input = CadreDelegationsInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.agentId) params.set("agentId", input.agentId);
      if (input.status) params.set("status", input.status);
      return client.fetch("cadre", `/delegations?${params.toString()}`);
    }
    case "cadre_sla_violations": {
      const input = CadreSlaViolationsInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.agentId) params.set("agentId", input.agentId);
      if (input.severity) params.set("severity", input.severity);
      if (input.fromDate) params.set("fromDate", input.fromDate);
      params.set("limit", String(input.limit));
      return client.fetch("cadre", `/sla-violations?${params.toString()}`);
    }
    default:
      throw new Error(`Unknown cadre tool: ${name}`);
  }
}

// src/engines/oath.ts
import { z as z5 } from "zod";
var OathAttestInputSchema = z5.object({
  dealId: z5.string().min(1),
  type: z5.enum(["COMPLETION", "QUALITY", "DELIVERY", "PAYMENT", "CUSTOM"]),
  evidence: z5.record(z5.unknown()).optional(),
  comment: z5.string().max(1e3).optional()
});
var OathVerifyInputSchema = z5.object({
  attestationId: z5.string().min(1)
});
var OathVaultUploadInputSchema = z5.object({
  dealId: z5.string().min(1),
  documents: z5.array(z5.object({
    name: z5.string(),
    contentHash: z5.string(),
    mimeType: z5.string().optional()
  }))
});
var OathVaultSealInputSchema = z5.object({
  dealId: z5.string().min(1),
  sealType: z5.enum(["PARTIAL", "FINAL"]).default("FINAL")
});
var OathTrustTierInputSchema = z5.object({
  userId: z5.string().optional(),
  orgId: z5.string().optional()
});
var oathTools = [
  {
    name: "oath_attest",
    description: "Create an attestation for a deal milestone or outcome. Attestations are cryptographically signed.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID to attest"
        },
        type: {
          type: "string",
          enum: ["COMPLETION", "QUALITY", "DELIVERY", "PAYMENT", "CUSTOM"],
          description: "Attestation type"
        },
        evidence: {
          type: "object",
          description: "Evidence supporting the attestation"
        },
        comment: {
          type: "string",
          description: "Optional comment"
        }
      },
      required: ["dealId", "type"]
    }
  },
  {
    name: "oath_verify",
    description: "Verify an attestation's authenticity and check its on-chain status.",
    inputSchema: {
      type: "object",
      properties: {
        attestationId: {
          type: "string",
          description: "Attestation ID to verify"
        }
      },
      required: ["attestationId"]
    }
  },
  {
    name: "oath_vault_upload",
    description: "Upload document hashes to the secure vault for a deal. Documents are stored off-chain with on-chain anchoring.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID"
        },
        documents: {
          type: "array",
          items: {
            type: "object",
            properties: {
              name: { type: "string" },
              contentHash: { type: "string" },
              mimeType: { type: "string" }
            },
            required: ["name", "contentHash"]
          },
          description: "Documents to upload (hashes only)"
        }
      },
      required: ["dealId", "documents"]
    }
  },
  {
    name: "oath_vault_seal",
    description: "Seal a deal's vault, creating a Merkle root that anchors all documents on-chain.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID"
        },
        sealType: {
          type: "string",
          enum: ["PARTIAL", "FINAL"],
          description: "Seal type (FINAL is irreversible)",
          default: "FINAL"
        }
      },
      required: ["dealId"]
    }
  },
  {
    name: "oath_trust_tier",
    description: "Get the trust tier for a user or organization based on their attestation history.",
    inputSchema: {
      type: "object",
      properties: {
        userId: {
          type: "string",
          description: "User ID to check"
        },
        orgId: {
          type: "string",
          description: "Organization ID to check"
        }
      }
    }
  }
];
async function handleOathTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "oath_attest": {
      const input = OathAttestInputSchema.parse(args);
      return client.fetch("oath", "/attestations", {
        method: "POST",
        body: input,
        idempotencyKey: `attest-${input.dealId}-${input.type}-${Date.now()}`
      });
    }
    case "oath_verify": {
      const input = OathVerifyInputSchema.parse(args);
      return client.fetch("oath", `/attestations/${input.attestationId}/verify`);
    }
    case "oath_vault_upload": {
      const input = OathVaultUploadInputSchema.parse(args);
      return client.fetch("oath", `/deals/${input.dealId}/vault/upload`, {
        method: "POST",
        body: { documents: input.documents },
        idempotencyKey: `vault-upload-${input.dealId}-${Date.now()}`
      });
    }
    case "oath_vault_seal": {
      const input = OathVaultSealInputSchema.parse(args);
      return client.fetch("oath", `/deals/${input.dealId}/vault/seal`, {
        method: "POST",
        body: { sealType: input.sealType },
        idempotencyKey: `vault-seal-${input.dealId}-${Date.now()}`
      });
    }
    case "oath_trust_tier": {
      const input = OathTrustTierInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.userId) params.set("userId", input.userId);
      if (input.orgId) params.set("orgId", input.orgId);
      return client.fetch("oath", `/trust-tier?${params.toString()}`);
    }
    default:
      throw new Error(`Unknown oath tool: ${name}`);
  }
}

// src/engines/parler.ts
import { z as z6 } from "zod";
var ParlerDisputeFileInputSchema = z6.object({
  dealId: z6.string().min(1),
  reason: z6.enum([
    "NON_DELIVERY",
    "QUALITY_ISSUE",
    "LATE_DELIVERY",
    "PAYMENT_DISPUTE",
    "BREACH_OF_TERMS",
    "OTHER"
  ]),
  description: z6.string().min(10).max(5e3),
  evidence: z6.array(z6.object({
    type: z6.string(),
    url: z6.string().url().optional(),
    hash: z6.string().optional(),
    description: z6.string()
  })).optional(),
  requestedResolution: z6.enum(["REFUND", "PARTIAL_REFUND", "COMPLETION", "ARBITRATION"]).optional()
});
var ParlerDisputeListInputSchema = z6.object({
  status: z6.enum(["OPEN", "IN_REVIEW", "RESOLVED", "ESCALATED"]).optional(),
  role: z6.enum(["CLAIMANT", "RESPONDENT", "ARBITRATOR"]).optional(),
  limit: z6.number().min(1).max(100).default(20)
});
var ParlerProposalsInputSchema = z6.object({
  disputeId: z6.string().min(1)
});
var ParlerVoteInputSchema = z6.object({
  proposalId: z6.string().min(1),
  vote: z6.enum(["APPROVE", "REJECT", "ABSTAIN"]),
  comment: z6.string().max(1e3).optional()
});
var parlerTools = [
  {
    name: "parler_dispute_file",
    description: "File a dispute against a deal. Initiates the resolution process.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID to dispute"
        },
        reason: {
          type: "string",
          enum: [
            "NON_DELIVERY",
            "QUALITY_ISSUE",
            "LATE_DELIVERY",
            "PAYMENT_DISPUTE",
            "BREACH_OF_TERMS",
            "OTHER"
          ],
          description: "Dispute reason"
        },
        description: {
          type: "string",
          description: "Detailed description of the dispute"
        },
        evidence: {
          type: "array",
          items: {
            type: "object",
            properties: {
              type: { type: "string" },
              url: { type: "string" },
              hash: { type: "string" },
              description: { type: "string" }
            }
          },
          description: "Supporting evidence"
        },
        requestedResolution: {
          type: "string",
          enum: ["REFUND", "PARTIAL_REFUND", "COMPLETION", "ARBITRATION"],
          description: "Requested resolution outcome"
        }
      },
      required: ["dealId", "reason", "description"]
    }
  },
  {
    name: "parler_dispute_list",
    description: "List disputes you're involved in as claimant, respondent, or arbitrator.",
    inputSchema: {
      type: "object",
      properties: {
        status: {
          type: "string",
          enum: ["OPEN", "IN_REVIEW", "RESOLVED", "ESCALATED"],
          description: "Filter by status"
        },
        role: {
          type: "string",
          enum: ["CLAIMANT", "RESPONDENT", "ARBITRATOR"],
          description: "Filter by your role"
        },
        limit: {
          type: "number",
          description: "Max disputes to return",
          default: 20
        }
      }
    }
  },
  {
    name: "parler_proposals",
    description: "List resolution proposals for a dispute.",
    inputSchema: {
      type: "object",
      properties: {
        disputeId: {
          type: "string",
          description: "Dispute ID"
        }
      },
      required: ["disputeId"]
    }
  },
  {
    name: "parler_vote",
    description: "Vote on a resolution proposal. Requires arbitrator role for binding votes.",
    inputSchema: {
      type: "object",
      properties: {
        proposalId: {
          type: "string",
          description: "Proposal ID to vote on"
        },
        vote: {
          type: "string",
          enum: ["APPROVE", "REJECT", "ABSTAIN"],
          description: "Your vote"
        },
        comment: {
          type: "string",
          description: "Optional comment explaining your vote"
        }
      },
      required: ["proposalId", "vote"]
    }
  }
];
async function handleParlerTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "parler_dispute_file": {
      const input = ParlerDisputeFileInputSchema.parse(args);
      return client.fetch("parler", "/disputes", {
        method: "POST",
        body: input,
        idempotencyKey: `dispute-${input.dealId}-${Date.now()}`
      });
    }
    case "parler_dispute_list": {
      const input = ParlerDisputeListInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.status) params.set("status", input.status);
      if (input.role) params.set("role", input.role);
      params.set("limit", String(input.limit));
      return client.fetch("parler", `/disputes?${params.toString()}`);
    }
    case "parler_proposals": {
      const input = ParlerProposalsInputSchema.parse(args);
      return client.fetch("parler", `/disputes/${input.disputeId}/proposals`);
    }
    case "parler_vote": {
      const input = ParlerVoteInputSchema.parse(args);
      return client.fetch("parler", `/proposals/${input.proposalId}/vote`, {
        method: "POST",
        body: { vote: input.vote, comment: input.comment },
        idempotencyKey: `vote-${input.proposalId}-${Date.now()}`
      });
    }
    default:
      throw new Error(`Unknown parler tool: ${name}`);
  }
}

// src/engines/academy.ts
import { z as z7 } from "zod";
var AcademyCoursesInputSchema = z7.object({
  category: z7.enum(["DEALS", "FINANCE", "LEGAL", "AGENTS", "BLOCKCHAIN"]).optional(),
  level: z7.enum(["BEGINNER", "INTERMEDIATE", "ADVANCED"]).optional(),
  limit: z7.number().min(1).max(100).default(20)
});
var AcademyEnrollInputSchema = z7.object({
  courseId: z7.string().min(1)
});
var AcademyTipInputSchema = z7.object({
  courseId: z7.string().min(1),
  amount: z7.number().positive(),
  message: z7.string().max(500).optional()
});
var academyTools = [
  {
    name: "academy_courses",
    description: "Browse available courses on the Academy platform.",
    inputSchema: {
      type: "object",
      properties: {
        category: {
          type: "string",
          enum: ["DEALS", "FINANCE", "LEGAL", "AGENTS", "BLOCKCHAIN"],
          description: "Filter by category"
        },
        level: {
          type: "string",
          enum: ["BEGINNER", "INTERMEDIATE", "ADVANCED"],
          description: "Filter by difficulty level"
        },
        limit: {
          type: "number",
          description: "Max courses to return",
          default: 20
        }
      }
    }
  },
  {
    name: "academy_enroll",
    description: "Enroll in a course. Some courses may require payment.",
    inputSchema: {
      type: "object",
      properties: {
        courseId: {
          type: "string",
          description: "Course ID to enroll in"
        }
      },
      required: ["courseId"]
    }
  },
  {
    name: "academy_tip",
    description: "Tip a course creator to show appreciation.",
    inputSchema: {
      type: "object",
      properties: {
        courseId: {
          type: "string",
          description: "Course ID"
        },
        amount: {
          type: "number",
          description: "Tip amount in Talers"
        },
        message: {
          type: "string",
          description: "Optional thank-you message"
        }
      },
      required: ["courseId", "amount"]
    }
  }
];
async function handleAcademyTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "academy_courses": {
      const input = AcademyCoursesInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.category) params.set("category", input.category);
      if (input.level) params.set("level", input.level);
      params.set("limit", String(input.limit));
      return client.fetch("academy", `/courses?${params.toString()}`);
    }
    case "academy_enroll": {
      const input = AcademyEnrollInputSchema.parse(args);
      return client.fetch("academy", `/courses/${input.courseId}/enroll`, {
        method: "POST",
        idempotencyKey: `enroll-${input.courseId}-${Date.now()}`
      });
    }
    case "academy_tip": {
      const input = AcademyTipInputSchema.parse(args);
      return client.fetch("academy", `/courses/${input.courseId}/tip`, {
        method: "POST",
        body: { amount: input.amount, message: input.message },
        idempotencyKey: `tip-${input.courseId}-${Date.now()}`
      });
    }
    default:
      throw new Error(`Unknown academy tool: ${name}`);
  }
}

// src/engines/hq.ts
import { z as z8 } from "zod";
var HqDashboardInputSchema = z8.object({
  period: z8.enum(["DAY", "WEEK", "MONTH", "QUARTER"]).default("WEEK")
});
var HqHealthInputSchema = z8.object({
  detailed: z8.boolean().default(false)
});
var hqTools = [
  {
    name: "hq_dashboard",
    description: "Get dashboard metrics including deal volume, transaction totals, and agent activity.",
    inputSchema: {
      type: "object",
      properties: {
        period: {
          type: "string",
          enum: ["DAY", "WEEK", "MONTH", "QUARTER"],
          description: "Time period for metrics",
          default: "WEEK"
        }
      }
    }
  },
  {
    name: "hq_health",
    description: "Check system health status across all engines.",
    inputSchema: {
      type: "object",
      properties: {
        detailed: {
          type: "boolean",
          description: "Include detailed per-service metrics",
          default: false
        }
      }
    }
  }
];
async function handleHqTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "hq_dashboard": {
      const input = HqDashboardInputSchema.parse(args);
      return client.fetch("hq", `/dashboard?period=${input.period}`);
    }
    case "hq_health": {
      const input = HqHealthInputSchema.parse(args);
      const params = input.detailed ? "?detailed=true" : "";
      return client.fetch("hq", `/health${params}`);
    }
    default:
      throw new Error(`Unknown hq tool: ${name}`);
  }
}

// src/engines/clause.ts
import { z as z9 } from "zod";
var ClauseRenderInputSchema = z9.object({
  templateId: z9.string().min(1),
  variables: z9.record(z9.union([z9.string(), z9.number(), z9.boolean()])),
  format: z9.enum(["HTML", "MARKDOWN", "PLAIN"]).default("MARKDOWN")
});
var clauseTools = [
  {
    name: "clause_render",
    description: "Render a contract clause template with provided variables. Returns formatted text.",
    inputSchema: {
      type: "object",
      properties: {
        templateId: {
          type: "string",
          description: "Clause template ID"
        },
        variables: {
          type: "object",
          description: "Variables to substitute in the template",
          additionalProperties: {
            oneOf: [
              { type: "string" },
              { type: "number" },
              { type: "boolean" }
            ]
          }
        },
        format: {
          type: "string",
          enum: ["HTML", "MARKDOWN", "PLAIN"],
          description: "Output format",
          default: "MARKDOWN"
        }
      },
      required: ["templateId", "variables"]
    }
  }
];
async function handleClauseTool(name, args) {
  const client = getEngineClient();
  switch (name) {
    case "clause_render": {
      const input = ClauseRenderInputSchema.parse(args);
      return client.fetch("clause", "/render", {
        method: "POST",
        body: input
      });
    }
    default:
      throw new Error(`Unknown clause tool: ${name}`);
  }
}

// src/resources.ts
var resources = [
  {
    uri: "dealworks://profile",
    name: "User Profile",
    description: "Current user's profile including trust tier, verification status, and preferences",
    mimeType: "application/json"
  },
  {
    uri: "dealworks://wallet",
    name: "Wallet Summary",
    description: "Wallet balances across all currencies including locked/available breakdown",
    mimeType: "application/json"
  },
  {
    uri: "dealworks://deals",
    name: "Active Deals",
    description: "List of active deals with summary status",
    mimeType: "application/json"
  },
  {
    uri: "dealworks://agents",
    name: "Deployed Agents",
    description: "List of deployed agents with health status",
    mimeType: "application/json"
  },
  {
    uri: "dealworks://templates",
    name: "Deal Templates",
    description: "Available deal templates from Bourse",
    mimeType: "application/json"
  },
  {
    uri: "dealworks://disputes",
    name: "Open Disputes",
    description: "Active disputes requiring attention",
    mimeType: "application/json"
  },
  {
    uri: "dealworks://dashboard",
    name: "Dashboard Metrics",
    description: "Key metrics and KPIs from HQ dashboard",
    mimeType: "application/json"
  }
];
async function readResource(uri) {
  const client = getEngineClient();
  switch (uri) {
    case "dealworks://profile": {
      const result = await client.fetch("hq", "/users/me/profile");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    case "dealworks://wallet": {
      const result = await client.fetch("fund", "/wallets/me/summary");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    case "dealworks://deals": {
      const result = await client.fetch("deal", "/deals?status=ACTIVE&limit=50");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    case "dealworks://agents": {
      const result = await client.fetch("cadre", "/agents?status=RUNNING&limit=50");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    case "dealworks://templates": {
      const result = await client.fetch("bourse", "/listings?category=TEMPLATE&limit=50");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    case "dealworks://disputes": {
      const result = await client.fetch("parler", "/disputes?status=OPEN&limit=20");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    case "dealworks://dashboard": {
      const result = await client.fetch("hq", "/dashboard?period=WEEK");
      return JSON.stringify(result.data ?? result, null, 2);
    }
    default:
      throw new Error(`Unknown resource: ${uri}`);
  }
}

// src/prompts.ts
var prompts = [
  {
    name: "escrow-deal",
    description: "Create a deal with escrow protection. Guides through deal creation, escrow funding, and attestation.",
    arguments: [
      {
        name: "counterparty",
        description: "Email or user ID of the counterparty",
        required: true
      },
      {
        name: "amount",
        description: "Deal amount to escrow",
        required: true
      },
      {
        name: "description",
        description: "Brief description of the deal",
        required: true
      }
    ]
  },
  {
    name: "deploy-agent",
    description: "Deploy an autonomous agent from a skill. Includes funding and SLA configuration.",
    arguments: [
      {
        name: "skill",
        description: "Skill name or ID to deploy",
        required: true
      },
      {
        name: "budget",
        description: "Maximum budget in Talers",
        required: true
      }
    ]
  },
  {
    name: "file-dispute",
    description: "File a dispute against a deal with evidence collection.",
    arguments: [
      {
        name: "dealId",
        description: "Deal ID to dispute",
        required: true
      },
      {
        name: "reason",
        description: "Brief reason for the dispute",
        required: true
      }
    ]
  },
  {
    name: "publish-template",
    description: "Publish a deal template to the Bourse marketplace.",
    arguments: [
      {
        name: "name",
        description: "Template name",
        required: true
      },
      {
        name: "category",
        description: "Template category (e.g., 'freelance', 'real-estate', 'consulting')",
        required: true
      }
    ]
  },
  {
    name: "portfolio-review",
    description: "Review your deal portfolio including active deals, pending escrows, and agent performance.",
    arguments: []
  }
];
function getPromptMessages(name, args) {
  switch (name) {
    case "escrow-deal":
      return [
        {
          role: "user",
          content: `I want to create an escrow-protected deal with ${args.counterparty} for ${args.amount} Talers.

Description: ${args.description}

Please help me:
1. Create the deal with appropriate terms
2. Set up escrow for the full amount
3. Create an attestation template for completion verification

Use the deal_create, fund_escrow, and oath_attest tools to complete this workflow.`
        }
      ];
    case "deploy-agent":
      return [
        {
          role: "user",
          content: `I want to deploy an agent using the "${args.skill}" skill with a budget of ${args.budget} Talers.

Please help me:
1. Search for the skill in Bourse
2. Deploy the agent with appropriate configuration
3. Fund the agent's wallet
4. Set up SLA monitoring

Use bourse_search, cadre_deploy, and fund_agent_fund tools to complete this workflow.`
        }
      ];
    case "file-dispute":
      return [
        {
          role: "user",
          content: `I need to file a dispute for deal ${args.dealId}.

Reason: ${args.reason}

Please help me:
1. Get the deal details first
2. File the dispute with proper categorization
3. List any relevant attestations as evidence
4. Explain the next steps in the resolution process

Use deal_get, oath_verify (for any attestations), and parler_dispute_file tools.`
        }
      ];
    case "publish-template":
      return [
        {
          role: "user",
          content: `I want to publish a deal template called "${args.name}" in the ${args.category} category.

Please help me:
1. Check if similar templates exist in Bourse
2. Create the template structure
3. Publish to the marketplace
4. Explain how others can use it

Use bourse_search and bourse_publish tools.`
        }
      ];
    case "portfolio-review":
      return [
        {
          role: "user",
          content: `Please review my current deal.works portfolio:

1. Show my active deals and their status
2. List any pending escrows with locked amounts
3. Show deployed agents and their health
4. Summarize my wallet balances
5. Flag any items needing attention (SLA violations, expiring deals, etc.)

Use deal_list, fund_balance, cadre_list, cadre_sla_violations, and hq_dashboard tools to compile this review.`
        }
      ];
    default:
      throw new Error(`Unknown prompt: ${name}`);
  }
}

// src/index.ts
var allTools = [
  ...dealTools,
  ...fundTools,
  ...bourseTools,
  ...cadreTools,
  ...oathTools,
  ...parlerTools,
  ...academyTools,
  ...hqTools,
  ...clauseTools
];
var toolHandlers = {
  // Deal tools
  deal_list: handleDealTool,
  deal_create: handleDealTool,
  deal_get: handleDealTool,
  deal_action: handleDealTool,
  deal_search: handleDealTool,
  deal_timeline: handleDealTool,
  deal_attachments: handleDealTool,
  // Fund tools
  fund_balance: handleFundTool,
  fund_transfer: handleFundTool,
  fund_transactions: handleFundTool,
  fund_escrow: handleFundTool,
  fund_cashout: handleFundTool,
  fund_agent_fund: handleFundTool,
  // Bourse tools
  bourse_search: handleBourseTool,
  bourse_get: handleBourseTool,
  bourse_fork: handleBourseTool,
  bourse_publish: handleBourseTool,
  bourse_earnings: handleBourseTool,
  // Cadre tools
  cadre_list: handleCadreTool,
  cadre_deploy: handleCadreTool,
  cadre_command: handleCadreTool,
  cadre_health: handleCadreTool,
  cadre_delegations: handleCadreTool,
  cadre_sla_violations: handleCadreTool,
  // Oath tools
  oath_attest: handleOathTool,
  oath_verify: handleOathTool,
  oath_vault_upload: handleOathTool,
  oath_vault_seal: handleOathTool,
  oath_trust_tier: handleOathTool,
  // Parler tools
  parler_dispute_file: handleParlerTool,
  parler_dispute_list: handleParlerTool,
  parler_proposals: handleParlerTool,
  parler_vote: handleParlerTool,
  // Academy tools
  academy_courses: handleAcademyTool,
  academy_enroll: handleAcademyTool,
  academy_tip: handleAcademyTool,
  // HQ tools
  hq_dashboard: handleHqTool,
  hq_health: handleHqTool,
  // Clause tools
  clause_render: handleClauseTool
};
async function createServer() {
  const server = new Server(
    {
      name: "deal-works-mcp",
      version: "0.1.0"
    },
    {
      capabilities: {
        tools: {},
        resources: {},
        prompts: {}
      }
    }
  );
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: allTools
  }));
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const handler = toolHandlers[name];
    if (!handler) {
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({ error: `Unknown tool: ${name}` })
          }
        ],
        isError: true
      };
    }
    try {
      const result = await handler(name, args ?? {});
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(result, null, 2)
          }
        ]
      };
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : String(err);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({ error: errorMessage })
          }
        ],
        isError: true
      };
    }
  });
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
    resources
  }));
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
    const { uri } = request.params;
    try {
      const content = await readResource(uri);
      return {
        contents: [
          {
            uri,
            mimeType: "application/json",
            text: content
          }
        ]
      };
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : String(err);
      throw new Error(`Failed to read resource ${uri}: ${errorMessage}`);
    }
  });
  server.setRequestHandler(ListPromptsRequestSchema, async () => ({
    prompts
  }));
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const prompt = prompts.find((p) => p.name === name);
    if (!prompt) {
      throw new Error(`Unknown prompt: ${name}`);
    }
    const messages = getPromptMessages(name, args ?? {});
    return {
      description: prompt.description,
      messages: messages.map((m) => ({
        role: m.role,
        content: {
          type: "text",
          text: m.content
        }
      }))
    };
  });
  return server;
}
async function main() {
  if (!process.env.DEAL_WORKS_API_KEY) {
    console.error("Warning: DEAL_WORKS_API_KEY not set. API calls will fail.");
    console.error("Set it via: export DEAL_WORKS_API_KEY=your_key");
  }
  const server = await createServer();
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("deal.works MCP Server running");
  console.error(`Tools: ${allTools.length}`);
  console.error(`Resources: ${resources.length}`);
  console.error(`Prompts: ${prompts.length}`);
}
main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
//# sourceMappingURL=index.js.map

path: package.json
content: {
  "name": "@swgoettelman/deal-works-mcp",
  "version": "0.1.0",
  "description": "MCP server exposing deal.works platform tools to AI agents - 39 tools across 9 engines for deals, escrow, agents, attestations, and more",
  "type": "module",
  "main": "./dist/index.js",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "bin": {
    "deal-works-mcp": "./dist/index.js"
  },
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "scripts": {
    "build": "tsup",
    "dev": "tsup --watch",
    "typecheck": "tsc --noEmit",
    "lint": "eslint src/",
    "test": "vitest run",
    "test:watch": "vitest",
    "prepublishOnly": "pnpm build"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.25.3",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@goettelman/config": "workspace:*",
    "@types/node": "^22.9.0",
    "eslint": "^9.15.0",
    "tsup": "^8.3.5",
    "typescript": "^5.7.2",
    "typescript-eslint": "^8.15.0",
    "vitest": "^2.1.0"
  },
  "files": [
    "dist",
    "README.md",
    "LICENSE"
  ],
  "keywords": [
    "mcp",
    "model-context-protocol",
    "deal-works",
    "ai-agents",
    "escrow",
    "smart-contracts",
    "attestation",
    "claude",
    "openai",
    "anthropic"
  ],
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/goettelman/deal.works.git",
    "directory": "packages/deal-works-mcp"
  },
  "homepage": "https://deal.works",
  "bugs": {
    "url": "https://github.com/goettelman/deal.works/issues"
  },
  "publishConfig": {
    "access": "public"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}


path: src/auth.ts
content: /**
 * Authentication handling for MCP server
 * Supports Bearer tokens and OAuth2 PKCE flow
 */

import { z } from "zod";

export const AuthConfigSchema = z.object({
  [REDACTED_SECRET]).optional(),
  oauth2: z.object({
    clientId: z.string(),
    redirectUri: z.string(),
    scopes: z.array(z.string()).default([]),
  }).optional(),
});

export type AuthConfig = z.infer<typeof AuthConfigSchema>;

export interface AuthContext {
  apiKey?: string;
  accessToken?: string;
  userId?: string;
  orgId?: string;
  scopes: string[];
}

/**
 * Extract auth context from environment or request headers
 */
export function getAuthContext(headers?: Record<string, string>): AuthContext {
  const [REDACTED_SECRET] ?? headers?.["x-api-key"];
  const accessToken = headers?.["authorization"]?.replace(/^Bearer\s+/i, "");

  return {
    apiKey,
    accessToken: accessToken ?? apiKey,
    userId: headers?.["x-user-id"],
    orgId: headers?.["x-org-id"],
    scopes: parseScopes(headers?.["x-scopes"]),
  };
}

function parseScopes(scopeHeader?: string): string[] {
  if (!scopeHeader) return [];
  return scopeHeader.split(/[\s,]+/).filter(Boolean);
}

/**
 * Validate that auth context has required scopes
 */
export function requireScopes(context: AuthContext, required: string[]): void {
  if (required.length === 0) return;

  // API key has all scopes
  if (context.apiKey) return;

  const missing = required.filter((s) => !context.scopes.includes(s));
  if (missing.length > 0) {
    throw new Error(`Missing required scopes: ${missing.join(", ")}`);
  }
}

/**
 * Generate OAuth2 PKCE authorization URL
 */
export function generateAuthUrl(
  config: NonNullable<AuthConfig["oauth2"]>,
  state: string,
  codeVerifier: string
): string {
  const codeChallenge = generateCodeChallenge(codeVerifier);

  const params = new URLSearchParams({
    client_id: config.clientId,
    redirect_uri: config.redirectUri,
    response_type: "code",
    scope: config.scopes.join(" "),
    state,
    code_challenge: codeChallenge,
    code_challenge_method: "S256",
  });

  return `https://hq.works/oauth/authorize?${params.toString()}`;
}

/**
 * Generate PKCE code challenge from verifier
 */
function generateCodeChallenge(verifier: string): string {
  // In Node.js, use crypto for SHA256
  const crypto = globalThis.crypto ?? require("crypto");
  const encoder = new TextEncoder();
  const data = encoder.encode(verifier);

  // Synchronous hash for simplicity - in production use async
  const hash = crypto.createHash?.("sha256").update(verifier).digest()
    ?? new Uint8Array(32); // Fallback for browser

  return base64UrlEncode(hash);
}

function base64UrlEncode(buffer: ArrayBuffer | Uint8Array): string {
  const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
  let binary = "";
  for (const byte of bytes) {
    binary += String.fromCharCode(byte);
  }
  return btoa(binary)
    .replace(/\+/g, "-")
    .replace(/\//g, "_")
    .replace(/=+$/, "");
}

/**
 * Generate random code verifier for PKCE
 */
export function generateCodeVerifier(): string {
  const array = new Uint8Array(32);
  globalThis.crypto?.getRandomValues?.(array) ??
    require("crypto").randomFillSync(array);
  return base64UrlEncode(array);
}


path: src/client.ts
content: /**
 * Shared HTTP client for engine API calls
 * Handles authentication, retries, and circuit breaking
 */

import { z } from "zod";

export interface EngineClientConfig {
  apiKey?: string;
  baseUrls?: Record<string, string>;
  timeout?: number;
  maxRetries?: number;
}

export interface EngineResponse<T = unknown> {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
    retryable: boolean;
  };
}

const DEFAULT_BASE_URLS: Record<string, string> = {
  deal: "https://deal.works/api",
  fund: "https://fund.works/api",
  bourse: "https://bourse.works/api",
  cadre: "https://cadre.works/api",
  oath: "https://oath.works/api",
  parler: "https://parler.works/api",
  academy: "https://academy.works/api",
  hq: "https://hq.works/api",
  clause: "https://clause.works/api",
};

const RETRYABLE_STATUS_CODES = [429, 502, 503, 504];
const RETRY_DELAYS = [1000, 2000, 4000];

// Circuit breaker state per engine
const circuitState: Record<string, {
  failures: number;
  lastFailure: number;
  openUntil: number;
}> = {};

const CIRCUIT_FAILURE_THRESHOLD = 5;
const CIRCUIT_WINDOW_MS = 60000;
const CIRCUIT_OPEN_DURATION_MS = 30000;

function checkCircuit(engine: string): void {
  const state = circuitState[engine];
  if (!state) return;

  const now = Date.now();
  if (state.openUntil > now) {
    throw new Error(`Circuit open for ${engine} engine. Retry after ${Math.ceil((state.openUntil - now) / 1000)}s`);
  }

  // Reset if window expired
  if (now - state.lastFailure > CIRCUIT_WINDOW_MS) {
    state.failures = 0;
  }
}

function recordFailure(engine: string): void {
  if (!circuitState[engine]) {
    circuitState[engine] = { failures: 0, lastFailure: 0, openUntil: 0 };
  }

  const state = circuitState[engine];
  const now = Date.now();

  state.failures++;
  state.lastFailure = now;

  if (state.failures >= CIRCUIT_FAILURE_THRESHOLD) {
    state.openUntil = now + CIRCUIT_OPEN_DURATION_MS;
    state.failures = 0;
  }
}

function recordSuccess(engine: string): void {
  if (circuitState[engine]) {
    circuitState[engine].failures = 0;
  }
}

export class EngineClient {
  private readonly [REDACTED_SECRET] | undefined;
  private readonly baseUrls: Record<string, string>;
  private readonly timeout: number;
  private readonly maxRetries: number;

  constructor(config: EngineClientConfig = {}) {
    this.[REDACTED_SECRET] ?? process.env.DEAL_WORKS_API_KEY;
    this.baseUrls = { ...DEFAULT_BASE_URLS, ...config.baseUrls };
    this.timeout = config.timeout ?? 30000;
    this.maxRetries = config.maxRetries ?? 3;
  }

  async fetch<T>(
    engine: string,
    path: string,
    options: {
      method?: "GET" | "POST" | "PUT" | "DELETE";
      body?: unknown;
      idempotencyKey?: string;
    } = {}
  ): Promise<EngineResponse<T>> {
    const { method = "GET", body, idempotencyKey } = options;

    checkCircuit(engine);

    const baseUrl = this.baseUrls[engine];
    if (!baseUrl) {
      return {
        success: false,
        error: {
          code: "UNKNOWN_ENGINE",
          message: `Unknown engine: ${engine}`,
          retryable: false,
        },
      };
    }

    const url = `${baseUrl}${path}`;
    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      "User-Agent": "@goettelman/deal-works-mcp/0.1.0",
    };

    if (this.apiKey) {
      headers["Authorization"] = `Bearer ${this.apiKey}`;
    }

    if (idempotencyKey) {
      headers["X-Idempotency-Key"] = idempotencyKey;
    }

    let lastError: Error | null = null;

    for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
      try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), this.timeout);

        const response = await fetch(url, {
          method,
          headers,
          body: body ? JSON.stringify(body) : undefined,
          signal: controller.signal,
        });

        clearTimeout(timeoutId);

        if (response.ok) {
          recordSuccess(engine);
          const data = await response.json() as T;
          return { success: true, data };
        }

        const isRetryable = RETRYABLE_STATUS_CODES.includes(response.status);

        if (!isRetryable || attempt === this.maxRetries) {
          recordFailure(engine);
          const errorBody = await response.text();
          return {
            success: false,
            error: {
              code: `HTTP_${response.status}`,
              message: errorBody || response.statusText,
              retryable: isRetryable,
            },
          };
        }

        // Wait before retry
        await sleep(RETRY_DELAYS[attempt] ?? 4000);
      } catch (err) {
        lastError = err instanceof Error ? err : new Error(String(err));

        if (attempt === this.maxRetries) {
          recordFailure(engine);
          return {
            success: false,
            error: {
              code: "NETWORK_ERROR",
              message: lastError.message,
              retryable: true,
            },
          };
        }

        await sleep(RETRY_DELAYS[attempt] ?? 4000);
      }
    }

    return {
      success: false,
      error: {
        code: "MAX_RETRIES_EXCEEDED",
        message: lastError?.message ?? "Max retries exceeded",
        retryable: false,
      },
    };
  }
}

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// Singleton instance
let clientInstance: EngineClient | null = null;

export function getEngineClient(config?: EngineClientConfig): EngineClient {
  if (!clientInstance || config) {
    clientInstance = new EngineClient(config);
  }
  return clientInstance;
}


path: src/engines/academy.ts
content: /**
 * Academy Engine - 3 tools
 * Learning platform for deal-making skills
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const AcademyCoursesInputSchema = z.object({
  category: z.enum(["DEALS", "FINANCE", "LEGAL", "AGENTS", "BLOCKCHAIN"]).optional(),
  level: z.enum(["BEGINNER", "INTERMEDIATE", "ADVANCED"]).optional(),
  limit: z.number().min(1).max(100).default(20),
});

const AcademyEnrollInputSchema = z.object({
  courseId: z.string().min(1),
});

const AcademyTipInputSchema = z.object({
  courseId: z.string().min(1),
  amount: z.number().positive(),
  message: z.string().max(500).optional(),
});

// Tool definitions
export const academyTools: Tool[] = [
  {
    name: "academy_courses",
    description: "Browse available courses on the Academy platform.",
    inputSchema: {
      type: "object",
      properties: {
        category: {
          type: "string",
          enum: ["DEALS", "FINANCE", "LEGAL", "AGENTS", "BLOCKCHAIN"],
          description: "Filter by category",
        },
        level: {
          type: "string",
          enum: ["BEGINNER", "INTERMEDIATE", "ADVANCED"],
          description: "Filter by difficulty level",
        },
        limit: {
          type: "number",
          description: "Max courses to return",
          default: 20,
        },
      },
    },
  },
  {
    name: "academy_enroll",
    description: "Enroll in a course. Some courses may require payment.",
    inputSchema: {
      type: "object",
      properties: {
        courseId: {
          type: "string",
          description: "Course ID to enroll in",
        },
      },
      required: ["courseId"],
    },
  },
  {
    name: "academy_tip",
    description: "Tip a course creator to show appreciation.",
    inputSchema: {
      type: "object",
      properties: {
        courseId: {
          type: "string",
          description: "Course ID",
        },
        amount: {
          type: "number",
          description: "Tip amount in Talers",
        },
        message: {
          type: "string",
          description: "Optional thank-you message",
        },
      },
      required: ["courseId", "amount"],
    },
  },
];

// Tool handlers
export async function handleAcademyTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "academy_courses": {
      const input = AcademyCoursesInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.category) params.set("category", input.category);
      if (input.level) params.set("level", input.level);
      params.set("limit", String(input.limit));
      return client.fetch("academy", `/courses?${params.toString()}`);
    }

    case "academy_enroll": {
      const input = AcademyEnrollInputSchema.parse(args);
      return client.fetch("academy", `/courses/${input.courseId}/enroll`, {
        method: "POST",
        idempotencyKey: `enroll-${input.courseId}-${Date.now()}`,
      });
    }

    case "academy_tip": {
      const input = AcademyTipInputSchema.parse(args);
      return client.fetch("academy", `/courses/${input.courseId}/tip`, {
        method: "POST",
        body: { amount: input.amount, message: input.message },
        idempotencyKey: `tip-${input.courseId}-${Date.now()}`,
      });
    }

    default:
      throw new Error(`Unknown academy tool: ${name}`);
  }
}


path: src/engines/bourse.ts
content: /**
 * Bourse Engine - 5 tools
 * Marketplace for deal templates, skills, and integrations
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const BourseSearchInputSchema = z.object({
  query: z.string().min(1).max(200),
  category: z.enum(["TEMPLATE", "SKILL", "INTEGRATION", "CONNECTOR"]).optional(),
  minQuality: z.number().min(0).max(100).optional(),
  source: z.enum(["OFFICIAL", "COMMUNITY", "ACTIVEPIECES"]).optional(),
  limit: z.number().min(1).max(100).default(20),
});

const BourseGetInputSchema = z.object({
  listingId: z.string().min(1),
});

const BourseForkInputSchema = z.object({
  listingId: z.string().min(1),
  newName: z.string().min(1).max(100).optional(),
});

const BoursePublishInputSchema = z.object({
  type: z.enum(["TEMPLATE", "SKILL", "INTEGRATION"]),
  name: z.string().min(1).max(100),
  description: z.string().max(2000),
  content: z.record(z.unknown()),
  price: z.number().min(0).default(0),
  tags: z.array(z.string()).default([]),
});

const BourseEarningsInputSchema = z.object({
  period: z.enum(["DAY", "WEEK", "MONTH", "ALL"]).default("MONTH"),
});

// Tool definitions
export const bourseTools: Tool[] = [
  {
    name: "bourse_search",
    description: "Search the Bourse marketplace for templates, skills, and integrations.",
    inputSchema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Search query",
        },
        category: {
          type: "string",
          enum: ["TEMPLATE", "SKILL", "INTEGRATION", "CONNECTOR"],
          description: "Filter by category",
        },
        minQuality: {
          type: "number",
          description: "Minimum quality score (0-100)",
        },
        source: {
          type: "string",
          enum: ["OFFICIAL", "COMMUNITY", "ACTIVEPIECES"],
          description: "Filter by source",
        },
        limit: {
          type: "number",
          description: "Max results",
          default: 20,
        },
      },
      required: ["query"],
    },
  },
  {
    name: "bourse_get",
    description: "Get detailed information about a Bourse listing including reviews and usage stats.",
    inputSchema: {
      type: "object",
      properties: {
        listingId: {
          type: "string",
          description: "Listing ID",
        },
      },
      required: ["listingId"],
    },
  },
  {
    name: "bourse_fork",
    description: "Fork a Bourse listing to create your own customized version.",
    inputSchema: {
      type: "object",
      properties: {
        listingId: {
          type: "string",
          description: "Listing ID to fork",
        },
        newName: {
          type: "string",
          description: "Name for your forked version",
        },
      },
      required: ["listingId"],
    },
  },
  {
    name: "bourse_publish",
    description: "Publish a new template, skill, or integration to the Bourse marketplace.",
    inputSchema: {
      type: "object",
      properties: {
        type: {
          type: "string",
          enum: ["TEMPLATE", "SKILL", "INTEGRATION"],
          description: "Listing type",
        },
        name: {
          type: "string",
          description: "Listing name",
        },
        description: {
          type: "string",
          description: "Description",
        },
        content: {
          type: "object",
          description: "Listing content/definition",
        },
        price: {
          type: "number",
          description: "Price in Talers (0 for free)",
          default: 0,
        },
        tags: {
          type: "array",
          items: { type: "string" },
          description: "Tags for discoverability",
        },
      },
      required: ["type", "name", "description", "content"],
    },
  },
  {
    name: "bourse_earnings",
    description: "View your Bourse earnings from published listings.",
    inputSchema: {
      type: "object",
      properties: {
        period: {
          type: "string",
          enum: ["DAY", "WEEK", "MONTH", "ALL"],
          description: "Time period",
          default: "MONTH",
        },
      },
    },
  },
];

// Tool handlers
export async function handleBourseTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "bourse_search": {
      const input = BourseSearchInputSchema.parse(args);
      return client.fetch("bourse", "/listings/search", {
        method: "POST",
        body: input,
      });
    }

    case "bourse_get": {
      const input = BourseGetInputSchema.parse(args);
      return client.fetch("bourse", `/listings/${input.listingId}`);
    }

    case "bourse_fork": {
      const input = BourseForkInputSchema.parse(args);
      return client.fetch("bourse", `/listings/${input.listingId}/fork`, {
        method: "POST",
        body: { newName: input.newName },
        idempotencyKey: `fork-${input.listingId}-${Date.now()}`,
      });
    }

    case "bourse_publish": {
      const input = BoursePublishInputSchema.parse(args);
      return client.fetch("bourse", "/listings", {
        method: "POST",
        body: input,
        idempotencyKey: `publish-${Date.now()}`,
      });
    }

    case "bourse_earnings": {
      const input = BourseEarningsInputSchema.parse(args);
      return client.fetch("bourse", `/earnings?period=${input.period}`);
    }

    default:
      throw new Error(`Unknown bourse tool: ${name}`);
  }
}


path: src/engines/cadre.ts
content: /**
 * Cadre Engine - 6 tools
 * Agent deployment, management, and monitoring
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const CadreListInputSchema = z.object({
  status: z.enum(["RUNNING", "STOPPED", "FAILED", "PENDING"]).optional(),
  limit: z.number().min(1).max(100).default(20),
  offset: z.number().min(0).default(0),
});

const CadreDeployInputSchema = z.object({
  name: z.string().min(1).max(100),
  skillId: z.string().min(1),
  config: z.record(z.unknown()).optional(),
  fundingAmount: z.number().positive().optional(),
  slaConfig: z.object({
    maxLatencyMs: z.number().positive().optional(),
    minUptime: z.number().min(0).max(100).optional(),
  }).optional(),
});

const CadreCommandInputSchema = z.object({
  agentId: z.string().min(1),
  command: z.enum(["START", "STOP", "RESTART", "SCALE_UP", "SCALE_DOWN"]),
  params: z.record(z.unknown()).optional(),
});

const CadreHealthInputSchema = z.object({
  agentId: z.string().min(1),
});

const CadreDelegationsInputSchema = z.object({
  agentId: z.string().optional(),
  status: z.enum(["ACTIVE", "REVOKED", "EXPIRED"]).optional(),
});

const CadreSlaViolationsInputSchema = z.object({
  agentId: z.string().optional(),
  severity: z.enum(["LOW", "MEDIUM", "HIGH", "CRITICAL"]).optional(),
  fromDate: z.string().datetime().optional(),
  limit: z.number().min(1).max(100).default(50),
});

// Tool definitions
export const cadreTools: Tool[] = [
  {
    name: "cadre_list",
    description: "List deployed agents with optional status filter.",
    inputSchema: {
      type: "object",
      properties: {
        status: {
          type: "string",
          enum: ["RUNNING", "STOPPED", "FAILED", "PENDING"],
          description: "Filter by agent status",
        },
        limit: {
          type: "number",
          description: "Max agents to return",
          default: 20,
        },
        offset: {
          type: "number",
          description: "Pagination offset",
          default: 0,
        },
      },
    },
  },
  {
    name: "cadre_deploy",
    description: "Deploy a new agent from a skill definition. Optionally fund and configure SLA.",
    inputSchema: {
      type: "object",
      properties: {
        name: {
          type: "string",
          description: "Agent name",
        },
        skillId: {
          type: "string",
          description: "Skill ID from Bourse to deploy",
        },
        config: {
          type: "object",
          description: "Agent configuration overrides",
        },
        fundingAmount: {
          type: "number",
          description: "Initial funding amount in Talers",
        },
        slaConfig: {
          type: "object",
          properties: {
            maxLatencyMs: { type: "number" },
            minUptime: { type: "number" },
          },
          description: "SLA configuration",
        },
      },
      required: ["name", "skillId"],
    },
  },
  {
    name: "cadre_command",
    description: "Send a command to an agent: start, stop, restart, or scale.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Agent ID",
        },
        command: {
          type: "string",
          enum: ["START", "STOP", "RESTART", "SCALE_UP", "SCALE_DOWN"],
          description: "Command to execute",
        },
        params: {
          type: "object",
          description: "Command parameters (e.g., scale factor)",
        },
      },
      required: ["agentId", "command"],
    },
  },
  {
    name: "cadre_health",
    description: "Get health status and metrics for a specific agent.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Agent ID",
        },
      },
      required: ["agentId"],
    },
  },
  {
    name: "cadre_delegations",
    description: "List permission delegations granted to agents.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Filter by agent ID",
        },
        status: {
          type: "string",
          enum: ["ACTIVE", "REVOKED", "EXPIRED"],
          description: "Filter by delegation status",
        },
      },
    },
  },
  {
    name: "cadre_sla_violations",
    description: "List SLA violations for agents. Used for monitoring and alerting.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Filter by agent ID",
        },
        severity: {
          type: "string",
          enum: ["LOW", "MEDIUM", "HIGH", "CRITICAL"],
          description: "Filter by severity",
        },
        fromDate: {
          type: "string",
          description: "Start date filter (ISO 8601)",
        },
        limit: {
          type: "number",
          description: "Max violations to return",
          default: 50,
        },
      },
    },
  },
];

// Tool handlers
export async function handleCadreTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "cadre_list": {
      const input = CadreListInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.status) params.set("status", input.status);
      params.set("limit", String(input.limit));
      params.set("offset", String(input.offset));
      return client.fetch("cadre", `/agents?${params.toString()}`);
    }

    case "cadre_deploy": {
      const input = CadreDeployInputSchema.parse(args);
      return client.fetch("cadre", "/agents", {
        method: "POST",
        body: input,
        idempotencyKey: `deploy-${input.skillId}-${Date.now()}`,
      });
    }

    case "cadre_command": {
      const input = CadreCommandInputSchema.parse(args);
      return client.fetch("cadre", `/agents/${input.agentId}/command`, {
        method: "POST",
        body: { command: input.command, params: input.params },
        idempotencyKey: `command-${input.agentId}-${input.command}-${Date.now()}`,
      });
    }

    case "cadre_health": {
      const input = CadreHealthInputSchema.parse(args);
      return client.fetch("cadre", `/agents/${input.agentId}/health`);
    }

    case "cadre_delegations": {
      const input = CadreDelegationsInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.agentId) params.set("agentId", input.agentId);
      if (input.status) params.set("status", input.status);
      return client.fetch("cadre", `/delegations?${params.toString()}`);
    }

    case "cadre_sla_violations": {
      const input = CadreSlaViolationsInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.agentId) params.set("agentId", input.agentId);
      if (input.severity) params.set("severity", input.severity);
      if (input.fromDate) params.set("fromDate", input.fromDate);
      params.set("limit", String(input.limit));
      return client.fetch("cadre", `/sla-violations?${params.toString()}`);
    }

    default:
      throw new Error(`Unknown cadre tool: ${name}`);
  }
}


path: src/engines/clause.ts
content: /**
 * Clause Engine - 1 tool
 * Contract clause rendering and templating
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const ClauseRenderInputSchema = z.object({
  templateId: z.string().min(1),
  variables: z.record(z.union([z.string(), z.number(), z.boolean()])),
  format: z.enum(["HTML", "MARKDOWN", "PLAIN"]).default("MARKDOWN"),
});

// Tool definitions
export const clauseTools: Tool[] = [
  {
    name: "clause_render",
    description: "Render a contract clause template with provided variables. Returns formatted text.",
    inputSchema: {
      type: "object",
      properties: {
        templateId: {
          type: "string",
          description: "Clause template ID",
        },
        variables: {
          type: "object",
          description: "Variables to substitute in the template",
          additionalProperties: {
            oneOf: [
              { type: "string" },
              { type: "number" },
              { type: "boolean" },
            ],
          },
        },
        format: {
          type: "string",
          enum: ["HTML", "MARKDOWN", "PLAIN"],
          description: "Output format",
          default: "MARKDOWN",
        },
      },
      required: ["templateId", "variables"],
    },
  },
];

// Tool handlers
export async function handleClauseTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "clause_render": {
      const input = ClauseRenderInputSchema.parse(args);
      return client.fetch("clause", "/render", {
        method: "POST",
        body: input,
      });
    }

    default:
      throw new Error(`Unknown clause tool: ${name}`);
  }
}


path: src/engines/deal.ts
content: /**
 * Deal Engine - 7 tools
 * Manages deal lifecycle: creation, actions, search, timeline
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const DealListInputSchema = z.object({
  status: z.enum(["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"]).optional(),
  limit: z.number().min(1).max(100).default(20),
  offset: z.number().min(0).default(0),
});

const DealCreateInputSchema = z.object({
  title: z.string().min(1).max(200),
  description: z.string().max(5000).optional(),
  counterpartyEmail: z.string().email().optional(),
  templateId: z.string().optional(),
  amount: z.number().positive().optional(),
  currency: z.string().default("USD"),
  dueDate: z.string().datetime().optional(),
});

const DealGetInputSchema = z.object({
  dealId: z.string().min(1),
});

const DealActionInputSchema = z.object({
  dealId: z.string().min(1),
  action: z.enum(["SIGN", "APPROVE", "REJECT", "CANCEL", "COMPLETE", "ARCHIVE"]),
  comment: z.string().max(1000).optional(),
});

const DealSearchInputSchema = z.object({
  query: z.string().min(1).max(200),
  status: z.enum(["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"]).optional(),
  fromDate: z.string().datetime().optional(),
  toDate: z.string().datetime().optional(),
  limit: z.number().min(1).max(100).default(20),
});

const DealTimelineInputSchema = z.object({
  dealId: z.string().min(1),
  limit: z.number().min(1).max(100).default(50),
});

const DealAttachmentsInputSchema = z.object({
  dealId: z.string().min(1),
});

// Tool definitions
export const dealTools: Tool[] = [
  {
    name: "deal_list",
    description: "List deals with optional status filter. Returns paginated list of deals for the authenticated user.",
    inputSchema: {
      type: "object",
      properties: {
        status: {
          type: "string",
          enum: ["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"],
          description: "Filter by deal status",
        },
        limit: {
          type: "number",
          description: "Number of deals to return (max 100)",
          default: 20,
        },
        offset: {
          type: "number",
          description: "Pagination offset",
          default: 0,
        },
      },
    },
  },
  {
    name: "deal_create",
    description: "Create a new deal. Can optionally use a template and specify counterparty.",
    inputSchema: {
      type: "object",
      properties: {
        title: {
          type: "string",
          description: "Deal title (required)",
        },
        description: {
          type: "string",
          description: "Deal description",
        },
        counterpartyEmail: {
          type: "string",
          description: "Email of the counterparty to invite",
        },
        templateId: {
          type: "string",
          description: "Template ID to base the deal on",
        },
        amount: {
          type: "number",
          description: "Deal amount",
        },
        currency: {
          type: "string",
          description: "Currency code (default: USD)",
        },
        dueDate: {
          type: "string",
          description: "Due date in ISO 8601 format",
        },
      },
      required: ["title"],
    },
  },
  {
    name: "deal_get",
    description: "Get detailed information about a specific deal including parties, terms, and current status.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID",
        },
      },
      required: ["dealId"],
    },
  },
  {
    name: "deal_action",
    description: "Perform an action on a deal: sign, approve, reject, cancel, complete, or archive.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID",
        },
        action: {
          type: "string",
          enum: ["SIGN", "APPROVE", "REJECT", "CANCEL", "COMPLETE", "ARCHIVE"],
          description: "Action to perform",
        },
        comment: {
          type: "string",
          description: "Optional comment for the action",
        },
      },
      required: ["dealId", "action"],
    },
  },
  {
    name: "deal_search",
    description: "Search deals by text query across titles, descriptions, and party names.",
    inputSchema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Search query",
        },
        status: {
          type: "string",
          enum: ["DRAFT", "ACTIVE", "COMPLETED", "CANCELLED"],
          description: "Filter by status",
        },
        fromDate: {
          type: "string",
          description: "Start date filter (ISO 8601)",
        },
        toDate: {
          type: "string",
          description: "End date filter (ISO 8601)",
        },
        limit: {
          type: "number",
          description: "Max results",
          default: 20,
        },
      },
      required: ["query"],
    },
  },
  {
    name: "deal_timeline",
    description: "Get the activity timeline for a deal showing all events and state changes.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID",
        },
        limit: {
          type: "number",
          description: "Max events to return",
          default: 50,
        },
      },
      required: ["dealId"],
    },
  },
  {
    name: "deal_attachments",
    description: "List all attachments (documents, files) associated with a deal.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID",
        },
      },
      required: ["dealId"],
    },
  },
];

// Tool handlers
export async function handleDealTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "deal_list": {
      const input = DealListInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.status) params.set("status", input.status);
      params.set("limit", String(input.limit));
      params.set("offset", String(input.offset));
      return client.fetch("deal", `/deals?${params.toString()}`);
    }

    case "deal_create": {
      const input = DealCreateInputSchema.parse(args);
      return client.fetch("deal", "/deals", {
        method: "POST",
        body: input,
        idempotencyKey: `create-${Date.now()}`,
      });
    }

    case "deal_get": {
      const input = DealGetInputSchema.parse(args);
      return client.fetch("deal", `/deals/${input.dealId}`);
    }

    case "deal_action": {
      const input = DealActionInputSchema.parse(args);
      return client.fetch("deal", `/deals/${input.dealId}/actions`, {
        method: "POST",
        body: { action: input.action, comment: input.comment },
        idempotencyKey: `action-${input.dealId}-${input.action}-${Date.now()}`,
      });
    }

    case "deal_search": {
      const input = DealSearchInputSchema.parse(args);
      return client.fetch("deal", "/deals/search", {
        method: "POST",
        body: input,
      });
    }

    case "deal_timeline": {
      const input = DealTimelineInputSchema.parse(args);
      const params = new URLSearchParams({ limit: String(input.limit) });
      return client.fetch("deal", `/deals/${input.dealId}/timeline?${params.toString()}`);
    }

    case "deal_attachments": {
      const input = DealAttachmentsInputSchema.parse(args);
      return client.fetch("deal", `/deals/${input.dealId}/attachments`);
    }

    default:
      throw new Error(`Unknown deal tool: ${name}`);
  }
}


path: src/engines/fund.ts
content: /**
 * Fund Engine - 6 tools
 * Manages wallets, transfers, escrow, and agent funding
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const FundBalanceInputSchema = z.object({
  walletId: z.string().optional(),
});

const FundTransferInputSchema = z.object({
  toWalletId: z.string().min(1),
  amount: z.number().positive(),
  currency: z.string().default("TALER"),
  memo: z.string().max(500).optional(),
  idempotencyKey: z.string().optional(),
});

const FundTransactionsInputSchema = z.object({
  walletId: z.string().optional(),
  type: z.enum(["CREDIT", "DEBIT", "ESCROW_LOCK", "ESCROW_RELEASE"]).optional(),
  limit: z.number().min(1).max(100).default(50),
  offset: z.number().min(0).default(0),
});

const FundEscrowInputSchema = z.object({
  dealId: z.string().min(1),
  amount: z.number().positive(),
  currency: z.string().default("TALER"),
  releaseConditions: z.array(z.string()).optional(),
});

const FundCashoutInputSchema = z.object({
  amount: z.number().positive(),
  destinationAddress: z.string().min(1),
  network: z.enum(["BASE", "BASE_SEPOLIA"]).default("BASE_SEPOLIA"),
});

const FundAgentFundInputSchema = z.object({
  agentId: z.string().min(1),
  amount: z.number().positive(),
  purpose: z.string().max(200).optional(),
});

// Tool definitions
export const fundTools: Tool[] = [
  {
    name: "fund_balance",
    description: "Get wallet balance including available, locked (in escrow), and pending amounts.",
    inputSchema: {
      type: "object",
      properties: {
        walletId: {
          type: "string",
          description: "Wallet ID (optional, defaults to user's primary wallet)",
        },
      },
    },
  },
  {
    name: "fund_transfer",
    description: "Transfer funds between wallets. Supports Taler tokens on Base.",
    inputSchema: {
      type: "object",
      properties: {
        toWalletId: {
          type: "string",
          description: "Destination wallet ID",
        },
        amount: {
          type: "number",
          description: "Amount to transfer",
        },
        currency: {
          type: "string",
          description: "Currency (default: TALER)",
        },
        memo: {
          type: "string",
          description: "Transfer memo/note",
        },
        idempotencyKey: {
          type: "string",
          description: "Idempotency key to prevent duplicate transfers",
        },
      },
      required: ["toWalletId", "amount"],
    },
  },
  {
    name: "fund_transactions",
    description: "List transaction history with optional type filter.",
    inputSchema: {
      type: "object",
      properties: {
        walletId: {
          type: "string",
          description: "Wallet ID (optional)",
        },
        type: {
          type: "string",
          enum: ["CREDIT", "DEBIT", "ESCROW_LOCK", "ESCROW_RELEASE"],
          description: "Filter by transaction type",
        },
        limit: {
          type: "number",
          description: "Max transactions to return",
          default: 50,
        },
        offset: {
          type: "number",
          description: "Pagination offset",
          default: 0,
        },
      },
    },
  },
  {
    name: "fund_escrow",
    description: "Lock funds in escrow for a deal. Funds are released when deal conditions are met.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID to escrow funds for",
        },
        amount: {
          type: "number",
          description: "Amount to lock",
        },
        currency: {
          type: "string",
          description: "Currency (default: TALER)",
        },
        releaseConditions: {
          type: "array",
          items: { type: "string" },
          description: "Conditions that must be met to release funds",
        },
      },
      required: ["dealId", "amount"],
    },
  },
  {
    name: "fund_cashout",
    description: "Cash out Taler tokens to external wallet address on Base network.",
    inputSchema: {
      type: "object",
      properties: {
        amount: {
          type: "number",
          description: "Amount to cash out",
        },
        destinationAddress: {
          type: "string",
          description: "Destination wallet address (0x...)",
        },
        network: {
          type: "string",
          enum: ["BASE", "BASE_SEPOLIA"],
          description: "Network (default: BASE_SEPOLIA for testnet)",
        },
      },
      required: ["amount", "destinationAddress"],
    },
  },
  {
    name: "fund_agent_fund",
    description: "Fund an agent's operational wallet for autonomous transactions.",
    inputSchema: {
      type: "object",
      properties: {
        agentId: {
          type: "string",
          description: "Agent ID to fund",
        },
        amount: {
          type: "number",
          description: "Amount to allocate",
        },
        purpose: {
          type: "string",
          description: "Purpose/reason for funding",
        },
      },
      required: ["agentId", "amount"],
    },
  },
];

// Tool handlers
export async function handleFundTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "fund_balance": {
      const input = FundBalanceInputSchema.parse(args);
      const path = input.walletId
        ? `/wallets/${input.walletId}/balance`
        : "/wallets/me/balance";
      return client.fetch("fund", path);
    }

    case "fund_transfer": {
      const input = FundTransferInputSchema.parse(args);
      return client.fetch("fund", "/transfers", {
        method: "POST",
        body: input,
        idempotencyKey: input.idempotencyKey ?? `transfer-${Date.now()}`,
      });
    }

    case "fund_transactions": {
      const input = FundTransactionsInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.walletId) params.set("walletId", input.walletId);
      if (input.type) params.set("type", input.type);
      params.set("limit", String(input.limit));
      params.set("offset", String(input.offset));
      return client.fetch("fund", `/transactions?${params.toString()}`);
    }

    case "fund_escrow": {
      const input = FundEscrowInputSchema.parse(args);
      return client.fetch("fund", "/escrow", {
        method: "POST",
        body: input,
        idempotencyKey: `escrow-${input.dealId}-${Date.now()}`,
      });
    }

    case "fund_cashout": {
      const input = FundCashoutInputSchema.parse(args);
      return client.fetch("fund", "/cashout", {
        method: "POST",
        body: input,
        idempotencyKey: `cashout-${Date.now()}`,
      });
    }

    case "fund_agent_fund": {
      const input = FundAgentFundInputSchema.parse(args);
      return client.fetch("fund", `/agents/${input.agentId}/fund`, {
        method: "POST",
        body: { amount: input.amount, purpose: input.purpose },
        idempotencyKey: `agent-fund-${input.agentId}-${Date.now()}`,
      });
    }

    default:
      throw new Error(`Unknown fund tool: ${name}`);
  }
}


path: src/engines/hq.ts
content: /**
 * HQ Engine - 2 tools
 * Platform administration and system health
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const HqDashboardInputSchema = z.object({
  period: z.enum(["DAY", "WEEK", "MONTH", "QUARTER"]).default("WEEK"),
});

const HqHealthInputSchema = z.object({
  detailed: z.boolean().default(false),
});

// Tool definitions
export const hqTools: Tool[] = [
  {
    name: "hq_dashboard",
    description: "Get dashboard metrics including deal volume, transaction totals, and agent activity.",
    inputSchema: {
      type: "object",
      properties: {
        period: {
          type: "string",
          enum: ["DAY", "WEEK", "MONTH", "QUARTER"],
          description: "Time period for metrics",
          default: "WEEK",
        },
      },
    },
  },
  {
    name: "hq_health",
    description: "Check system health status across all engines.",
    inputSchema: {
      type: "object",
      properties: {
        detailed: {
          type: "boolean",
          description: "Include detailed per-service metrics",
          default: false,
        },
      },
    },
  },
];

// Tool handlers
export async function handleHqTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "hq_dashboard": {
      const input = HqDashboardInputSchema.parse(args);
      return client.fetch("hq", `/dashboard?period=${input.period}`);
    }

    case "hq_health": {
      const input = HqHealthInputSchema.parse(args);
      const params = input.detailed ? "?detailed=true" : "";
      return client.fetch("hq", `/health${params}`);
    }

    default:
      throw new Error(`Unknown hq tool: ${name}`);
  }
}


path: src/engines/oath.ts
content: /**
 * Oath Engine - 5 tools
 * Attestations, verification, and trust management
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const OathAttestInputSchema = z.object({
  dealId: z.string().min(1),
  type: z.enum(["COMPLETION", "QUALITY", "DELIVERY", "PAYMENT", "CUSTOM"]),
  evidence: z.record(z.unknown()).optional(),
  comment: z.string().max(1000).optional(),
});

const OathVerifyInputSchema = z.object({
  attestationId: z.string().min(1),
});

const OathVaultUploadInputSchema = z.object({
  dealId: z.string().min(1),
  documents: z.array(z.object({
    name: z.string(),
    contentHash: z.string(),
    mimeType: z.string().optional(),
  })),
});

const OathVaultSealInputSchema = z.object({
  dealId: z.string().min(1),
  sealType: z.enum(["PARTIAL", "FINAL"]).default("FINAL"),
});

const OathTrustTierInputSchema = z.object({
  userId: z.string().optional(),
  orgId: z.string().optional(),
});

// Tool definitions
export const oathTools: Tool[] = [
  {
    name: "oath_attest",
    description: "Create an attestation for a deal milestone or outcome. Attestations are cryptographically signed.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID to attest",
        },
        type: {
          type: "string",
          enum: ["COMPLETION", "QUALITY", "DELIVERY", "PAYMENT", "CUSTOM"],
          description: "Attestation type",
        },
        evidence: {
          type: "object",
          description: "Evidence supporting the attestation",
        },
        comment: {
          type: "string",
          description: "Optional comment",
        },
      },
      required: ["dealId", "type"],
    },
  },
  {
    name: "oath_verify",
    description: "Verify an attestation's authenticity and check its on-chain status.",
    inputSchema: {
      type: "object",
      properties: {
        attestationId: {
          type: "string",
          description: "Attestation ID to verify",
        },
      },
      required: ["attestationId"],
    },
  },
  {
    name: "oath_vault_upload",
    description: "Upload document hashes to the secure vault for a deal. Documents are stored off-chain with on-chain anchoring.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID",
        },
        documents: {
          type: "array",
          items: {
            type: "object",
            properties: {
              name: { type: "string" },
              contentHash: { type: "string" },
              mimeType: { type: "string" },
            },
            required: ["name", "contentHash"],
          },
          description: "Documents to upload (hashes only)",
        },
      },
      required: ["dealId", "documents"],
    },
  },
  {
    name: "oath_vault_seal",
    description: "Seal a deal's vault, creating a Merkle root that anchors all documents on-chain.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID",
        },
        sealType: {
          type: "string",
          enum: ["PARTIAL", "FINAL"],
          description: "Seal type (FINAL is irreversible)",
          default: "FINAL",
        },
      },
      required: ["dealId"],
    },
  },
  {
    name: "oath_trust_tier",
    description: "Get the trust tier for a user or organization based on their attestation history.",
    inputSchema: {
      type: "object",
      properties: {
        userId: {
          type: "string",
          description: "User ID to check",
        },
        orgId: {
          type: "string",
          description: "Organization ID to check",
        },
      },
    },
  },
];

// Tool handlers
export async function handleOathTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "oath_attest": {
      const input = OathAttestInputSchema.parse(args);
      return client.fetch("oath", "/attestations", {
        method: "POST",
        body: input,
        idempotencyKey: `attest-${input.dealId}-${input.type}-${Date.now()}`,
      });
    }

    case "oath_verify": {
      const input = OathVerifyInputSchema.parse(args);
      return client.fetch("oath", `/attestations/${input.attestationId}/verify`);
    }

    case "oath_vault_upload": {
      const input = OathVaultUploadInputSchema.parse(args);
      return client.fetch("oath", `/deals/${input.dealId}/vault/upload`, {
        method: "POST",
        body: { documents: input.documents },
        idempotencyKey: `vault-upload-${input.dealId}-${Date.now()}`,
      });
    }

    case "oath_vault_seal": {
      const input = OathVaultSealInputSchema.parse(args);
      return client.fetch("oath", `/deals/${input.dealId}/vault/seal`, {
        method: "POST",
        body: { sealType: input.sealType },
        idempotencyKey: `vault-seal-${input.dealId}-${Date.now()}`,
      });
    }

    case "oath_trust_tier": {
      const input = OathTrustTierInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.userId) params.set("userId", input.userId);
      if (input.orgId) params.set("orgId", input.orgId);
      return client.fetch("oath", `/trust-tier?${params.toString()}`);
    }

    default:
      throw new Error(`Unknown oath tool: ${name}`);
  }
}


path: src/engines/parler.ts
content: /**
 * Parler Engine - 4 tools
 * Dispute resolution and governance
 */

import { z } from "zod";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "../client.js";

// Input schemas
const ParlerDisputeFileInputSchema = z.object({
  dealId: z.string().min(1),
  reason: z.enum([
    "NON_DELIVERY",
    "QUALITY_ISSUE",
    "LATE_DELIVERY",
    "PAYMENT_DISPUTE",
    "BREACH_OF_TERMS",
    "OTHER",
  ]),
  description: z.string().min(10).max(5000),
  evidence: z.array(z.object({
    type: z.string(),
    url: z.string().url().optional(),
    hash: z.string().optional(),
    description: z.string(),
  })).optional(),
  requestedResolution: z.enum(["REFUND", "PARTIAL_REFUND", "COMPLETION", "ARBITRATION"]).optional(),
});

const ParlerDisputeListInputSchema = z.object({
  status: z.enum(["OPEN", "IN_REVIEW", "RESOLVED", "ESCALATED"]).optional(),
  role: z.enum(["CLAIMANT", "RESPONDENT", "ARBITRATOR"]).optional(),
  limit: z.number().min(1).max(100).default(20),
});

const ParlerProposalsInputSchema = z.object({
  disputeId: z.string().min(1),
});

const ParlerVoteInputSchema = z.object({
  proposalId: z.string().min(1),
  vote: z.enum(["APPROVE", "REJECT", "ABSTAIN"]),
  comment: z.string().max(1000).optional(),
});

// Tool definitions
export const parlerTools: Tool[] = [
  {
    name: "parler_dispute_file",
    description: "File a dispute against a deal. Initiates the resolution process.",
    inputSchema: {
      type: "object",
      properties: {
        dealId: {
          type: "string",
          description: "Deal ID to dispute",
        },
        reason: {
          type: "string",
          enum: [
            "NON_DELIVERY",
            "QUALITY_ISSUE",
            "LATE_DELIVERY",
            "PAYMENT_DISPUTE",
            "BREACH_OF_TERMS",
            "OTHER",
          ],
          description: "Dispute reason",
        },
        description: {
          type: "string",
          description: "Detailed description of the dispute",
        },
        evidence: {
          type: "array",
          items: {
            type: "object",
            properties: {
              type: { type: "string" },
              url: { type: "string" },
              hash: { type: "string" },
              description: { type: "string" },
            },
          },
          description: "Supporting evidence",
        },
        requestedResolution: {
          type: "string",
          enum: ["REFUND", "PARTIAL_REFUND", "COMPLETION", "ARBITRATION"],
          description: "Requested resolution outcome",
        },
      },
      required: ["dealId", "reason", "description"],
    },
  },
  {
    name: "parler_dispute_list",
    description: "List disputes you're involved in as claimant, respondent, or arbitrator.",
    inputSchema: {
      type: "object",
      properties: {
        status: {
          type: "string",
          enum: ["OPEN", "IN_REVIEW", "RESOLVED", "ESCALATED"],
          description: "Filter by status",
        },
        role: {
          type: "string",
          enum: ["CLAIMANT", "RESPONDENT", "ARBITRATOR"],
          description: "Filter by your role",
        },
        limit: {
          type: "number",
          description: "Max disputes to return",
          default: 20,
        },
      },
    },
  },
  {
    name: "parler_proposals",
    description: "List resolution proposals for a dispute.",
    inputSchema: {
      type: "object",
      properties: {
        disputeId: {
          type: "string",
          description: "Dispute ID",
        },
      },
      required: ["disputeId"],
    },
  },
  {
    name: "parler_vote",
    description: "Vote on a resolution proposal. Requires arbitrator role for binding votes.",
    inputSchema: {
      type: "object",
      properties: {
        proposalId: {
          type: "string",
          description: "Proposal ID to vote on",
        },
        vote: {
          type: "string",
          enum: ["APPROVE", "REJECT", "ABSTAIN"],
          description: "Your vote",
        },
        comment: {
          type: "string",
          description: "Optional comment explaining your vote",
        },
      },
      required: ["proposalId", "vote"],
    },
  },
];

// Tool handlers
export async function handleParlerTool(
  name: string,
  args: Record<string, unknown>
): Promise<unknown> {
  const client = getEngineClient();

  switch (name) {
    case "parler_dispute_file": {
      const input = ParlerDisputeFileInputSchema.parse(args);
      return client.fetch("parler", "/disputes", {
        method: "POST",
        body: input,
        idempotencyKey: `dispute-${input.dealId}-${Date.now()}`,
      });
    }

    case "parler_dispute_list": {
      const input = ParlerDisputeListInputSchema.parse(args);
      const params = new URLSearchParams();
      if (input.status) params.set("status", input.status);
      if (input.role) params.set("role", input.role);
      params.set("limit", String(input.limit));
      return client.fetch("parler", `/disputes?${params.toString()}`);
    }

    case "parler_proposals": {
      const input = ParlerProposalsInputSchema.parse(args);
      return client.fetch("parler", `/disputes/${input.disputeId}/proposals`);
    }

    case "parler_vote": {
      const input = ParlerVoteInputSchema.parse(args);
      return client.fetch("parler", `/proposals/${input.proposalId}/vote`, {
        method: "POST",
        body: { vote: input.vote, comment: input.comment },
        idempotencyKey: `vote-${input.proposalId}-${Date.now()}`,
      });
    }

    default:
      throw new Error(`Unknown parler tool: ${name}`);
  }
}


path: src/index.ts
content: /**
 * deal.works MCP Server
 *
 * Model Context Protocol server exposing 39 tools across 9 engines
 * for deal management, escrow, agents, attestations, and more.
 *
 * Usage:
 *   npx @goettelman/deal-works-mcp
 *
 * Environment Variables:
 *   DEAL_WORKS_API_KEY - API key for authentication (required)
 */

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListPromptsRequestSchema,
  GetPromptRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

// Engine imports
import { dealTools, handleDealTool } from "./engines/deal.js";
import { fundTools, handleFundTool } from "./engines/fund.js";
import { bourseTools, handleBourseTool } from "./engines/bourse.js";
import { cadreTools, handleCadreTool } from "./engines/cadre.js";
import { oathTools, handleOathTool } from "./engines/oath.js";
import { parlerTools, handleParlerTool } from "./engines/parler.js";
import { academyTools, handleAcademyTool } from "./engines/academy.js";
import { hqTools, handleHqTool } from "./engines/hq.js";
import { clauseTools, handleClauseTool } from "./engines/clause.js";

// Resources and prompts
import { resources, readResource } from "./resources.js";
import { prompts, getPromptMessages } from "./prompts.js";

// Combine all tools
const allTools = [
  ...dealTools,
  ...fundTools,
  ...bourseTools,
  ...cadreTools,
  ...oathTools,
  ...parlerTools,
  ...academyTools,
  ...hqTools,
  ...clauseTools,
];

// Tool name to handler mapping
const toolHandlers: Record<string, (name: string, args: Record<string, unknown>) => Promise<unknown>> = {
  // Deal tools
  deal_list: handleDealTool,
  deal_create: handleDealTool,
  deal_get: handleDealTool,
  deal_action: handleDealTool,
  deal_search: handleDealTool,
  deal_timeline: handleDealTool,
  deal_attachments: handleDealTool,
  // Fund tools
  fund_balance: handleFundTool,
  fund_transfer: handleFundTool,
  fund_transactions: handleFundTool,
  fund_escrow: handleFundTool,
  fund_cashout: handleFundTool,
  fund_agent_fund: handleFundTool,
  // Bourse tools
  bourse_search: handleBourseTool,
  bourse_get: handleBourseTool,
  bourse_fork: handleBourseTool,
  bourse_publish: handleBourseTool,
  bourse_earnings: handleBourseTool,
  // Cadre tools
  cadre_list: handleCadreTool,
  cadre_deploy: handleCadreTool,
  cadre_command: handleCadreTool,
  cadre_health: handleCadreTool,
  cadre_delegations: handleCadreTool,
  cadre_sla_violations: handleCadreTool,
  // Oath tools
  oath_attest: handleOathTool,
  oath_verify: handleOathTool,
  oath_vault_upload: handleOathTool,
  oath_vault_seal: handleOathTool,
  oath_trust_tier: handleOathTool,
  // Parler tools
  parler_dispute_file: handleParlerTool,
  parler_dispute_list: handleParlerTool,
  parler_proposals: handleParlerTool,
  parler_vote: handleParlerTool,
  // Academy tools
  academy_courses: handleAcademyTool,
  academy_enroll: handleAcademyTool,
  academy_tip: handleAcademyTool,
  // HQ tools
  hq_dashboard: handleHqTool,
  hq_health: handleHqTool,
  // Clause tools
  clause_render: handleClauseTool,
};

/**
 * Create and configure the MCP server
 */
async function createServer(): Promise<Server> {
  const server = new Server(
    {
      name: "deal-works-mcp",
      version: "0.1.0",
    },
    {
      capabilities: {
        tools: {},
        resources: {},
        prompts: {},
      },
    }
  );

  // List all tools
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: allTools,
  }));

  // Handle tool calls
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const handler = toolHandlers[name];

    if (!handler) {
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({ error: `Unknown tool: ${name}` }),
          },
        ],
        isError: true,
      };
    }

    try {
      const result = await handler(name, (args ?? {}) as Record<string, unknown>);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(result, null, 2),
          },
        ],
      };
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : String(err);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({ error: errorMessage }),
          },
        ],
        isError: true,
      };
    }
  });

  // List resources
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
    resources,
  }));

  // Read resources
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
    const { uri } = request.params;
    try {
      const content = await readResource(uri);
      return {
        contents: [
          {
            uri,
            mimeType: "application/json",
            text: content,
          },
        ],
      };
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : String(err);
      throw new Error(`Failed to read resource ${uri}: ${errorMessage}`);
    }
  });

  // List prompts
  server.setRequestHandler(ListPromptsRequestSchema, async () => ({
    prompts,
  }));

  // Get prompt
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const prompt = prompts.find((p) => p.name === name);

    if (!prompt) {
      throw new Error(`Unknown prompt: ${name}`);
    }

    const messages = getPromptMessages(name, (args ?? {}) as Record<string, string>);

    return {
      description: prompt.description,
      messages: messages.map((m) => ({
        role: m.role,
        content: {
          type: "text" as const,
          text: m.content,
        },
      })),
    };
  });

  return server;
}

/**
 * Main entry point
 */
async function main(): Promise<void> {
  // Check for API key
  if (!process.env.DEAL_WORKS_API_KEY) {
    console.error("Warning: DEAL_WORKS_API_KEY not set. API calls will fail.");
    console.error("Set it via: export DEAL_WORKS_API_KEY=your_key");
  }

  const server = await createServer();
  const transport = new StdioServerTransport();

  await server.connect(transport);

  console.error("deal.works MCP Server running");
  console.error(`Tools: ${allTools.length}`);
  console.error(`Resources: ${resources.length}`);
  console.error(`Prompts: ${prompts.length}`);
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});


path: src/prompts.ts
content: /**
 * MCP Prompts - 5 prompts
 * Pre-built prompts for common workflows
 */

import type { Prompt } from "@modelcontextprotocol/sdk/types.js";

// Prompt definitions
export const prompts: Prompt[] = [
  {
    name: "escrow-deal",
    description: "Create a deal with escrow protection. Guides through deal creation, escrow funding, and attestation.",
    arguments: [
      {
        name: "counterparty",
        description: "Email or user ID of the counterparty",
        required: true,
      },
      {
        name: "amount",
        description: "Deal amount to escrow",
        required: true,
      },
      {
        name: "description",
        description: "Brief description of the deal",
        required: true,
      },
    ],
  },
  {
    name: "deploy-agent",
    description: "Deploy an autonomous agent from a skill. Includes funding and SLA configuration.",
    arguments: [
      {
        name: "skill",
        description: "Skill name or ID to deploy",
        required: true,
      },
      {
        name: "budget",
        description: "Maximum budget in Talers",
        required: true,
      },
    ],
  },
  {
    name: "file-dispute",
    description: "File a dispute against a deal with evidence collection.",
    arguments: [
      {
        name: "dealId",
        description: "Deal ID to dispute",
        required: true,
      },
      {
        name: "reason",
        description: "Brief reason for the dispute",
        required: true,
      },
    ],
  },
  {
    name: "publish-template",
    description: "Publish a deal template to the Bourse marketplace.",
    arguments: [
      {
        name: "name",
        description: "Template name",
        required: true,
      },
      {
        name: "category",
        description: "Template category (e.g., 'freelance', 'real-estate', 'consulting')",
        required: true,
      },
    ],
  },
  {
    name: "portfolio-review",
    description: "Review your deal portfolio including active deals, pending escrows, and agent performance.",
    arguments: [],
  },
];

// Prompt message generators
export function getPromptMessages(
  name: string,
  args: Record<string, string>
): Array<{ role: "user" | "assistant"; content: string }> {
  switch (name) {
    case "escrow-deal":
      return [
        {
          role: "user",
          content: `I want to create an escrow-protected deal with ${args.counterparty} for ${args.amount} Talers.

Description: ${args.description}

Please help me:
1. Create the deal with appropriate terms
2. Set up escrow for the full amount
3. Create an attestation template for completion verification

Use the deal_create, fund_escrow, and oath_attest tools to complete this workflow.`,
        },
      ];

    case "deploy-agent":
      return [
        {
          role: "user",
          content: `I want to deploy an agent using the "${args.skill}" skill with a budget of ${args.budget} Talers.

Please help me:
1. Search for the skill in Bourse
2. Deploy the agent with appropriate configuration
3. Fund the agent's wallet
4. Set up SLA monitoring

Use bourse_search, cadre_deploy, and fund_agent_fund tools to complete this workflow.`,
        },
      ];

    case "file-dispute":
      return [
        {
          role: "user",
          content: `I need to file a dispute for deal ${args.dealId}.

Reason: ${args.reason}

Please help me:
1. Get the deal details first
2. File the dispute with proper categorization
3. List any relevant attestations as evidence
4. Explain the next steps in the resolution process

Use deal_get, oath_verify (for any attestations), and parler_dispute_file tools.`,
        },
      ];

    case "publish-template":
      return [
        {
          role: "user",
          content: `I want to publish a deal template called "${args.name}" in the ${args.category} category.

Please help me:
1. Check if similar templates exist in Bourse
2. Create the template structure
3. Publish to the marketplace
4. Explain how others can use it

Use bourse_search and bourse_publish tools.`,
        },
      ];

    case "portfolio-review":
      return [
        {
          role: "user",
          content: `Please review my current deal.works portfolio:

1. Show my active deals and their status
2. List any pending escrows with locked amounts
3. Show deployed agents and their health
4. Summarize my wallet balances
5. Flag any items needing attention (SLA violations, expiring deals, etc.)

Use deal_list, fund_balance, cadre_list, cadre_sla_violations, and hq_dashboard tools to compile this review.`,
        },
      ];

    default:
      throw new Error(`Unknown prompt: ${name}`);
  }
}


path: src/resources.ts
content: /**
 * MCP Resources - 7 resources
 * Read-only data resources for AI agents
 */

import type { Resource } from "@modelcontextprotocol/sdk/types.js";
import { getEngineClient } from "./client.js";

// Resource definitions
export const resources: Resource[] = [
  {
    uri: "dealworks://profile",
    name: "User Profile",
    description: "Current user's profile including trust tier, verification status, and preferences",
    mimeType: "application/json",
  },
  {
    uri: "dealworks://wallet",
    name: "Wallet Summary",
    description: "Wallet balances across all currencies including locked/available breakdown",
    mimeType: "application/json",
  },
  {
    uri: "dealworks://deals",
    name: "Active Deals",
    description: "List of active deals with summary status",
    mimeType: "application/json",
  },
  {
    uri: "dealworks://agents",
    name: "Deployed Agents",
    description: "List of deployed agents with health status",
    mimeType: "application/json",
  },
  {
    uri: "dealworks://templates",
    name: "Deal Templates",
    description: "Available deal templates from Bourse",
    mimeType: "application/json",
  },
  {
    uri: "dealworks://disputes",
    name: "Open Disputes",
    description: "Active disputes requiring attention",
    mimeType: "application/json",
  },
  {
    uri: "dealworks://dashboard",
    name: "Dashboard Metrics",
    description: "Key metrics and KPIs from HQ dashboard",
    mimeType: "application/json",
  },
];

// Resource handlers
export async function readResource(uri: string): Promise<string> {
  const client = getEngineClient();

  switch (uri) {
    case "dealworks://profile": {
      const result = await client.fetch("hq", "/users/me/profile");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    case "dealworks://wallet": {
      const result = await client.fetch("fund", "/wallets/me/summary");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    case "dealworks://deals": {
      const result = await client.fetch("deal", "/deals?status=ACTIVE&limit=50");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    case "dealworks://agents": {
      const result = await client.fetch("cadre", "/agents?status=RUNNING&limit=50");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    case "dealworks://templates": {
      const result = await client.fetch("bourse", "/listings?category=TEMPLATE&limit=50");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    case "dealworks://disputes": {
      const result = await client.fetch("parler", "/disputes?status=OPEN&limit=20");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    case "dealworks://dashboard": {
      const result = await client.fetch("hq", "/dashboard?period=WEEK");
      return JSON.stringify(result.data ?? result, null, 2);
    }

    default:
      throw new Error(`Unknown resource: ${uri}`);
  }
}


path: tsconfig.json
content: {
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2022"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "tests"]
}


path: tsup.config.ts
content: import { defineConfig } from "tsup";

export default defineConfig({
  entry: ["src/index.ts"],
  format: ["esm"],
  dts: true,
  clean: true,
  sourcemap: true,
  minify: false,
  target: "node18",
  banner: {
    js: "#!/usr/bin/env node",
  },
});


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)