@ex7/mcp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,6 +53,8 @@ claude mcp add ex7 --env EX7_AGENT_TOKEN=$EX7_AGENT_TOKEN -- npx -y @ex7/mcp
53
53
  | `ex7_deploy_plan` | Compile a deploy plan for a PASS strategy. Webhook TEMPLATE only; EX7 never executes. |
54
54
  | `ex7_strategy_publish` | Publish (or unpublish) a strategy. |
55
55
  | `ex7_signals_list` | Recent live signals (one-shot). |
56
+ | `ex7_hunt` | One prompt, the machine runs the whole search (propose seed then mutate+re-judge then forward); returns the closest honest candidate + what killed it + fertile-ground. Needs EX7_TOKEN. |
57
+ | `ex7_hunt_status` | Poll a running hunt. |
56
58
  | `ex7_workflow_run` | The whole loop: generate, validate, create, judge, gate, and optionally backtest + deploy-plan. Operate steps run only on a real PASS. |
57
59
 
58
60
  These supersede the older `ex7_orchestrate` / `ex7_recursive_search` tool set.
package/dist/index.js CHANGED
@@ -1203,6 +1203,15 @@ class AgentScopedResource {
1203
1203
  ...o
1204
1204
  });
1205
1205
  }
1206
+ create(input, o = {}) {
1207
+ return this.http.json({
1208
+ path: "api/agent/strategy/create",
1209
+ method: "POST",
1210
+ body: input,
1211
+ auth: "agent",
1212
+ ...o
1213
+ });
1214
+ }
1206
1215
  judge(strategyId, o = {}) {
1207
1216
  return this.http.json({
1208
1217
  path: "api/agent/judge/run",
@@ -1812,6 +1821,7 @@ function optString(args, key) {
1812
1821
  const v = args[key];
1813
1822
  return typeof v === "string" && v.length > 0 ? v : undefined;
1814
1823
  }
1824
+ var sleep5 = (ms) => new Promise((r) => setTimeout(r, ms));
1815
1825
  var TOOLS = [
1816
1826
  {
1817
1827
  definition: {
@@ -1880,13 +1890,13 @@ var TOOLS = [
1880
1890
  const inst = optString(args, "instrument");
1881
1891
  if (inst)
1882
1892
  input.instrument = inst;
1883
- return ctx.client.strategies.create(input);
1893
+ return ctx.agentMode ? ctx.client.agent.create(input) : ctx.client.strategies.create(input);
1884
1894
  }
1885
1895
  },
1886
1896
  {
1887
1897
  definition: {
1888
1898
  name: "ex7_judge_run",
1889
- description: "Run The Judge on a saved strategy and return the terminal verdict (tier + metrics). With an agent token this is a deterministic $0 fixture lookup.",
1899
+ description: "Run The Judge on a saved strategy and return the terminal verdict (tier + metrics). With an agent token this runs the same deterministic, net-of-cost REAL backtest on your own saved strategy at $0 to EX7 (audited demo ids return their published verdict).",
1890
1900
  inputSchema: {
1891
1901
  type: "object",
1892
1902
  properties: { strategy_id: { type: "string", minLength: 1 } },
@@ -1992,6 +2002,79 @@ var TOOLS = [
1992
2002
  return ctx.client.signals.list(limit !== undefined ? { limit } : {});
1993
2003
  }
1994
2004
  },
2005
+ {
2006
+ definition: {
2007
+ name: "ex7_hunt",
2008
+ description: "One prompt → the machine runs the WHOLE search: it proposes one strategy seed and then mutates + re-judges it (deterministic, no extra LLM cost) up to ~6 iterations, forward-validates the best, and returns the closest HONEST candidate + what killed it + fertile-ground next steps. The Judge is never loosened — a survivor is neutral evidence, never advice. Aimed at the above-the-spread frontier (defaults to 15m); never 2m dead ground. Blocks up to max_wait_sec, then returns a hunt_id you poll with ex7_hunt_status. Needs a user token (EX7_TOKEN); the $0 agent token cannot run hunts.",
2009
+ inputSchema: {
2010
+ type: "object",
2011
+ properties: {
2012
+ prompt: { type: "string", minLength: 1, maxLength: 2000 },
2013
+ instrument: { type: "string", enum: ["NQ", "ES", "CL", "MNQ", "MES", "MCL"] },
2014
+ timeframe: { type: "string", enum: ["15m", "1H", "4H", "daily"] },
2015
+ max_wait_sec: { type: "number", minimum: 0, maximum: 1800 }
2016
+ },
2017
+ required: ["prompt"],
2018
+ additionalProperties: false
2019
+ }
2020
+ },
2021
+ handler: async (ctx, args) => {
2022
+ if (ctx.agentMode) {
2023
+ throw Object.assign(new Error("ex7_hunt needs a user token (EX7_TOKEN); the $0 agent token cannot run compute-heavy hunts"), { code: "agent_token_forbidden", status: 403 });
2024
+ }
2025
+ const prompt = reqString(args, "prompt");
2026
+ const body = { prompt };
2027
+ const inst = optString(args, "instrument");
2028
+ if (inst)
2029
+ body.instrument = inst;
2030
+ const tf = optString(args, "timeframe");
2031
+ if (tf)
2032
+ body.timeframe = tf;
2033
+ const started = await ctx.client.request({
2034
+ path: "api/hunt",
2035
+ method: "POST",
2036
+ body
2037
+ });
2038
+ const huntId = started.hunt_id;
2039
+ if (!huntId)
2040
+ return { ok: false, error: started.error ?? "hunt did not start" };
2041
+ const maxWaitMs = Math.min(Math.max(optNumber(args, "max_wait_sec") ?? 300, 0), 1800) * 1000;
2042
+ const deadline = Date.now() + maxWaitMs;
2043
+ while (true) {
2044
+ const snap = await ctx.client.request({ path: `api/hunt/${encodeURIComponent(huntId)}`, method: "GET" });
2045
+ if (snap.status === "completed")
2046
+ return { hunt_id: huntId, status: "completed", result: snap.result };
2047
+ if (snap.status === "failed")
2048
+ return { hunt_id: huntId, status: "failed", error: snap.error };
2049
+ if (Date.now() >= deadline) {
2050
+ return {
2051
+ hunt_id: huntId,
2052
+ status: "running",
2053
+ n_iterations: snap.n_iterations ?? 0,
2054
+ best: snap.best,
2055
+ note: "still running — poll ex7_hunt_status with this hunt_id"
2056
+ };
2057
+ }
2058
+ await sleep5(2500);
2059
+ }
2060
+ }
2061
+ },
2062
+ {
2063
+ definition: {
2064
+ name: "ex7_hunt_status",
2065
+ description: "Poll a running hunt started by ex7_hunt. Returns { status, progress[], best, result? }.",
2066
+ inputSchema: {
2067
+ type: "object",
2068
+ properties: { hunt_id: { type: "string", minLength: 1 } },
2069
+ required: ["hunt_id"],
2070
+ additionalProperties: false
2071
+ }
2072
+ },
2073
+ handler: (ctx, args) => {
2074
+ const id = reqString(args, "hunt_id");
2075
+ return ctx.client.request({ path: `api/hunt/${encodeURIComponent(id)}`, method: "GET" });
2076
+ }
2077
+ },
1995
2078
  {
1996
2079
  definition: {
1997
2080
  name: "ex7_workflow_run",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ex7/mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "EX7 Capital MCP server: drive the EX7 workflow from Claude Code, Cursor, or any MCP client.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,7 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "build": "bun build src/index.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk && chmod +x dist/index.js",
17
+ "prepack": "bun run build",
17
18
  "typecheck": "tsc --noEmit",
18
19
  "test": "vitest run"
19
20
  },