@panoptic-eng/mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @panoptic-eng/mcp
2
+
3
+ A local [Model Context Protocol](https://modelcontextprotocol.io) server that
4
+ exposes the Panoptic SDK to AI agents as read-only analytics tools. It runs
5
+ as a stdio process against **your own RPC endpoint** — zero infra, zero auth, no
6
+ private keys. The server only reads on-chain state; it never signs or sends
7
+ transactions. Build/simulate tools that return **unsigned transaction
8
+ envelopes** are planned for a future release (see the spec).
9
+
10
+ See `packages/sdk/mcp-spec.md` for the full specification and roadmap.
11
+
12
+ ## Quickstart
13
+
14
+ Every MCP client accepts the same `command` / `args` / `env` shape; only the
15
+ config file location differs (Claude Code/Desktop use `.mcp.json`, Cursor uses
16
+ its MCP settings, etc.).
17
+
18
+ ```jsonc
19
+ {
20
+ "mcpServers": {
21
+ "panoptic": {
22
+ "command": "npx",
23
+ "args": ["-y", "@panoptic-eng/mcp"],
24
+ "env": {
25
+ "PANOPTIC_RPC_URL": "https://mainnet.base.org",
26
+ "PANOPTIC_CHAIN_ID": "8453",
27
+ // optional — enables enhanced analytics tools
28
+ "PANOPTIC_SUBGRAPH_URL": ""
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ Configuration may also be passed as CLI flags, which override the env vars:
36
+
37
+ ```bash
38
+ npx @panoptic-eng/mcp --rpc-url https://mainnet.base.org --chain-id 8453
39
+ ```
40
+
41
+ Supported chains: Ethereum mainnet (`1`), Base (`8453`), Sepolia (`11155111`).
42
+
43
+ ## v0 tools (read-only, pure RPC)
44
+
45
+ | Tool | What it does |
46
+ | --- | --- |
47
+ | `list_pools` | Known pool deployment + live pool state (tokens, tick, trackers, health). |
48
+ | `explain_position` | Decode a TokenId into readable legs + a strategy label (no RPC). |
49
+ | `identify_address` | Map an address to its role in a Panoptic deployment. |
50
+ | `get_portfolio` | An account's open positions, collateral, and net greeks. |
51
+ | `account_health` | Buying power, margin buffer, and liquidation status. |
52
+ | `liquidity_map` | Tick liquidity distribution around the current tick. |
53
+ | `chunk_spread` | Per-chunk spread multiplier (via `scanChunks`): ~1.0x chunks are cheapest to BUY (lowest IV), high-multiplier chunks are most profitable to SELL. Width defaults to a standard timescale (`STANDARD_TICK_WIDTHS`). |
54
+ | `suggest_delta_hedge` | Net delta (positions + collateral) and a width=0 loan/credit leg sized to neutralize it. |
55
+ | `advise_position` | Live facts + management advice for a position (ITM/OTM, streamia, closeable-now, liquidation risk). |
56
+ | `preview_position` | Pre-trade quote (dry-run `eth_call`): collateral required, post-mint balances, solvency, for a given tokenId + size. |
57
+ | `position_scenario` | Payoff / NLV curve — net liquidation value across a band of hypothetical prices. |
58
+ | `hedge_params` | SDK-native delta-hedge parameters (`getDeltaHedgeParams`) to reach a target delta; whole-portfolio or single-position. |
59
+ | `trade_history` | Chronological mints/burns from on-chain events (event-level only — no realized P&L). |
60
+
61
+ `get_portfolio`, `account_health`, `suggest_delta_hedge`, `advise_position`,
62
+ `preview_position`, `position_scenario`, and `hedge_params` discover positions
63
+ via an on-chain event scan (the SDK's `syncPositions`) — no subgraph required.
64
+ Pass `fromBlock` to bound the scan on chains with a distant deployment block.
65
+ These account tools need an RPC that permits `eth_getLogs`; many free public
66
+ endpoints throttle or block large log scans, so a private RPC is recommended.
67
+
68
+ Build + simulate tools (`build_position`, `build_strategy`, `simulate_tx`, …)
69
+ that return unsigned transaction envelopes are planned for a future release and
70
+ are **not** shipped yet. All numeric on-chain quantities are serialized as
71
+ **decimal strings**.
72
+
73
+ ## Development
74
+
75
+ ```bash
76
+ pnpm --filter @panoptic-eng/mcp build # tsdown → dist/
77
+ pnpm --filter @panoptic-eng/mcp test # vitest
78
+ pnpm --filter @panoptic-eng/mcp typecheck # tsc --noEmit
79
+ pnpm --filter @panoptic-eng/mcp lint
80
+
81
+ # Inspect locally against a real RPC:
82
+ PANOPTIC_RPC_URL=https://mainnet.base.org PANOPTIC_CHAIN_ID=8453 \
83
+ npx @modelcontextprotocol/inspector node dist/cli.js
84
+ ```
85
+
86
+ The server depends on `@panoptic-eng/sdk`; the SDK never depends on it.
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.js ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { SERVER_VERSION, createContext, createServer, resolveConfig } from "./server--YF2LHqv.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+
5
+ //#region src/cli.ts
6
+ async function main() {
7
+ const config = resolveConfig(process.argv.slice(2), process.env);
8
+ const ctx = await createContext(config);
9
+ const server = createServer(ctx);
10
+ const transport = new StdioServerTransport();
11
+ await server.connect(transport);
12
+ console.error(`panoptic-mcp v${SERVER_VERSION} ready (chain ${config.chainId})`);
13
+ }
14
+ main().catch((err) => {
15
+ const message = err instanceof Error ? err.message : String(err);
16
+ console.error(`panoptic-mcp failed to start: ${message}`);
17
+ process.exit(1);
18
+ });
19
+
20
+ //#endregion
@@ -0,0 +1,94 @@
1
+ /// <reference types="node" />
2
+ import { ChainDeployment } from "@panoptic-eng/sdk/v2";
3
+ import { Address, Hex, PublicClient } from "viem";
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+
6
+ //#region src/config.d.ts
7
+ /** Chain ids Panoptic has deployments for (mainnet, Base, Sepolia). */
8
+ /** Chain ids Panoptic has deployments for (mainnet, Base, Sepolia). */
9
+ declare const KNOWN_CHAIN_IDS: readonly [1, 8453, 11155111];
10
+ /**
11
+ * Resolve an optional user-supplied chain-id string to a trusted known-chain
12
+ * constant, falling back to `fallback` when omitted/blank. Matches on canonical
13
+ * decimal form only (never Number(), so "1e0" is rejected) and throws on
14
+ * unsupported ids.
15
+ */
16
+
17
+ interface ServerConfig {
18
+ rpcUrl: string;
19
+ chainId: number;
20
+ /** Optional indexer URL; enables enhanced analytics tools. */
21
+ subgraphUrl?: string;
22
+ }
23
+ interface PanopticContext {
24
+ config: ServerConfig;
25
+ client: PublicClient;
26
+ deployment: ChainDeployment;
27
+ }
28
+ /**
29
+ * Resolve server config from CLI flags (`--rpc-url`, `--chain-id`,
30
+ * `--subgraph-url`) layered over env (`PANOPTIC_RPC_URL`, `PANOPTIC_CHAIN_ID`,
31
+ * `PANOPTIC_SUBGRAPH_URL`). CLI flags win. Throws a readable error when RPC URL
32
+ * or chain id is missing or unsupported.
33
+ */
34
+ declare function resolveConfig(argv: string[], env: NodeJS.ProcessEnv): ServerConfig;
35
+ /** Create the shared context (viem client + resolved deployment) for tools. */
36
+ declare function createContext(config: ServerConfig): Promise<PanopticContext>;
37
+
38
+ //#endregion
39
+ //#region src/serialize.d.ts
40
+ /**
41
+ * Recursively convert a value into a JSON-safe form. The only Panoptic-specific
42
+ * invariant here: **bigints become decimal strings** (never JS numbers), so
43
+ * on-chain quantities survive serialization without precision loss. Functions
44
+ * are dropped; everything else passes through. `_meta` blocks are ordinary
45
+ * nested objects and are handled by the recursion.
46
+ */
47
+ declare function toJsonSafe(value: unknown): unknown;
48
+ /** MCP tool result wrapping a serialized value as pretty JSON text. */
49
+ declare function jsonResult(value: unknown): {
50
+ content: {
51
+ type: 'text';
52
+ text: string;
53
+ }[];
54
+ };
55
+ type EnvelopeRisk = 'defined' | 'undefined' | 'info';
56
+ interface UnsignedTxEnvelopeInput {
57
+ summary: string;
58
+ risk: EnvelopeRisk;
59
+ chainId: number | bigint;
60
+ to: Address;
61
+ value: bigint;
62
+ data: Hex;
63
+ simulation?: unknown;
64
+ }
65
+ interface UnsignedTxEnvelope {
66
+ summary: string;
67
+ risk: EnvelopeRisk;
68
+ chainId: string;
69
+ to: Address;
70
+ value: string;
71
+ data: Hex;
72
+ simulation?: unknown;
73
+ envelopeHash: Hex;
74
+ }
75
+ /**
76
+ * Build the unsigned transaction envelope every build/write-like tool returns.
77
+ * The server never signs; it hands back this object plus `envelopeHash` so a
78
+ * downstream signer can verify it signs exactly what was simulated and shown.
79
+ */
80
+ declare function buildEnvelope(input: UnsignedTxEnvelopeInput): UnsignedTxEnvelope;
81
+
82
+ //#endregion
83
+ //#region src/server.d.ts
84
+ declare const SERVER_NAME = "panoptic-mcp";
85
+ declare const SERVER_VERSION: string;
86
+ /**
87
+ * Build the Panoptic MCP server and register the v0 read-only tool catalog.
88
+ * The transport (stdio locally; HTTP for a future hosted server) is wired by
89
+ * the caller, so this factory is reusable across surfaces.
90
+ */
91
+ declare function createServer(ctx: PanopticContext): McpServer;
92
+
93
+ //#endregion
94
+ export { KNOWN_CHAIN_IDS, PanopticContext, SERVER_NAME, SERVER_VERSION, ServerConfig, UnsignedTxEnvelope, buildEnvelope, createContext, createServer, jsonResult, resolveConfig, toJsonSafe };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { KNOWN_CHAIN_IDS, SERVER_NAME, SERVER_VERSION, buildEnvelope, createContext, createServer, jsonResult, resolveConfig, toJsonSafe } from "./server--YF2LHqv.js";
2
+
3
+ export { KNOWN_CHAIN_IDS, SERVER_NAME, SERVER_VERSION, buildEnvelope, createContext, createServer, jsonResult, resolveConfig, toJsonSafe };