MCP
Mount a sales team as a tool. api.forsale ships a stdio MCP server exposing the deal API to any MCP-capable agent: the agent sells; when your Mandate says a stage needs a human, a fully-briefed gig goes to a verified closer — and the agent just sees the deal advance.
Running the server
The server lives in the spike repo at packages/forsale/src/mcp.ts and speaks stdio. It proxies the HTTP API at FORSALE_URL (default http://localhost:4802) — point it at the live demo to try it without running anything else:
{
"mcpServers": {
"forsale": {
"command": "tsx",
"args": ["packages/forsale/src/mcp.ts"],
"env": { "FORSALE_URL": "https://sales-kernel-demo.vercel.app/forsale" }
}
}
}Tools
sell
Create a deal and run it until it closes or escalates to a human closer — the MCP face of POST /sell:
sell({
account: { name: string, industry?: string, actor: 'B2B' | 'B2C' | 'B2D' | 'B2A' },
listValueUsd: number,
mandate?: {
staffing?: {
setter?: 'agent' | 'human' | { humanIf: { minDealSizeUsd?: number, signals?: string[] } },
closer?: …,
nurturer?: …
},
maxCommissionPct?: number,
floorPct?: number,
stallTimeoutDays?: number,
fees?: { setterUsd?: number, nurturerUsd?: number },
commissionPct?: number
}
})The result is the JSON your agent would get from the HTTP API: a terminal Deal, or the escalation shape ({ escalated: true, role, gig, suggestedClosers }). Mandate values outside platform bounds come back as a tool error carrying the 422 payload.
get_deal
get_deal({ dealId: string }) — fetch a deal with its full activity log. The natural polling tool while a human is working an escalated stage.
advance_deal
advance_deal({ dealId: string }) — advance one step: the agent executor works the stage, or the Role escalates per the Mandate.