headless-oracle-mcp 1.0.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.
Files changed (3) hide show
  1. package/README.md +188 -0
  2. package/bin/cli.js +185 -0
  3. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # headless-oracle-mcp
2
+
3
+ [![npm version](https://img.shields.io/npm/v/headless-oracle-mcp)](https://npmjs.com/package/headless-oracle-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Local stdio MCP server for [Headless Oracle](https://headlessoracle.com) — Ed25519-signed market-state receipts for 28 global exchanges.
7
+
8
+ **Critical safety rule for agents:** treat `UNKNOWN` and `HALTED` as `CLOSED` — halt all execution.
9
+
10
+ ---
11
+
12
+ ## Quick start
13
+
14
+ ```bash
15
+ npx headless-oracle-mcp
16
+ ```
17
+
18
+ No install required. Works with Claude Desktop, Cursor, Cline, Windsurf, and Continue.dev.
19
+
20
+ ---
21
+
22
+ ## MCP client setup
23
+
24
+ ### Claude Desktop
25
+
26
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "headless-oracle": {
32
+ "command": "npx",
33
+ "args": ["-y", "headless-oracle-mcp"]
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### Cursor
40
+
41
+ Edit `~/.cursor/mcp.json`:
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "headless-oracle": {
47
+ "command": "npx",
48
+ "args": ["-y", "headless-oracle-mcp"]
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Cline
55
+
56
+ Edit `cline_mcp_settings.json` (accessible via Cline settings → MCP Servers):
57
+
58
+ ```json
59
+ {
60
+ "mcpServers": {
61
+ "headless-oracle": {
62
+ "command": "npx",
63
+ "args": ["-y", "headless-oracle-mcp"]
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ ### Windsurf
70
+
71
+ Edit `~/.codeium/windsurf/mcp_config.json`:
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "headless-oracle": {
77
+ "command": "npx",
78
+ "args": ["-y", "headless-oracle-mcp"]
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Continue.dev
85
+
86
+ Edit `~/.continue/config.json`:
87
+
88
+ ```json
89
+ {
90
+ "experimental": {
91
+ "modelContextProtocolServers": [
92
+ {
93
+ "transport": {
94
+ "type": "stdio",
95
+ "command": "npx",
96
+ "args": ["-y", "headless-oracle-mcp"]
97
+ }
98
+ }
99
+ ]
100
+ }
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## With API key
107
+
108
+ For authenticated access (higher rate limits, `/v5/status` endpoint):
109
+
110
+ ```json
111
+ {
112
+ "mcpServers": {
113
+ "headless-oracle": {
114
+ "command": "npx",
115
+ "args": ["-y", "headless-oracle-mcp"],
116
+ "env": {
117
+ "HEADLESS_ORACLE_API_KEY": "your-key-here"
118
+ }
119
+ }
120
+ }
121
+ }
122
+ ```
123
+
124
+ Get a free sandbox key at [headlessoracle.com](https://headlessoracle.com) or via the `/v5/sandbox` endpoint.
125
+
126
+ ---
127
+
128
+ ## Tools
129
+
130
+ | Tool | Description |
131
+ |------|-------------|
132
+ | `get_market_status` | Returns an Ed25519-signed receipt: `OPEN`, `CLOSED`, `HALTED`, or `UNKNOWN`. Treat UNKNOWN/HALTED as CLOSED. |
133
+ | `get_market_schedule` | Returns next open/close times in UTC for a given exchange. |
134
+ | `list_exchanges` | Lists all 28 supported exchanges with MIC codes, names, and timezones. |
135
+ | `verify_receipt` | Verifies an Ed25519 receipt locally — checks signature, TTL, and fields. |
136
+ | `get_payment_options` | Returns the upgrade ladder (sandbox → x402 → credits → Builder). |
137
+
138
+ ### Supported exchanges (28 total)
139
+
140
+ XNYS, XNAS, XBSP, XLON, XPAR, XSWX, XMIL, XHEL, XSTO, XIST, XSAU, XDFM, XJSE, XSHG, XSHE, XHKG, XJPX, XKRX, XBOM, XNSE, XSES, XASX, XNZE, XCBT, XNYM, XCBO, XCOI, XBIN
141
+
142
+ ---
143
+
144
+ ## Example receipt
145
+
146
+ ```json
147
+ {
148
+ "mic": "XNYS",
149
+ "status": "OPEN",
150
+ "receipt_mode": "live",
151
+ "issued_at": "2026-04-04T14:30:00.000Z",
152
+ "expires_at": "2026-04-04T14:31:00.000Z",
153
+ "issuer": "headlessoracle.com",
154
+ "schema_version": "v5.0",
155
+ "source": "SCHEDULE",
156
+ "key_id": "ed25519-v1",
157
+ "receipt_id": "...",
158
+ "signature": "..."
159
+ }
160
+ ```
161
+
162
+ All receipts are signed with Ed25519. Verify with [`@headlessoracle/verify`](https://npmjs.com/package/@headlessoracle/verify).
163
+
164
+ ---
165
+
166
+ ## How it works
167
+
168
+ This package is a local stdio MCP server that proxies tool calls to the [Headless Oracle remote endpoint](https://headlessoracle.com/mcp). Your MCP client (Claude Desktop, Cursor, etc.) communicates with this process over stdin/stdout using JSON-RPC 2.0. The process forwards `tools/list` and `tools/call` requests to the remote endpoint and returns the results.
169
+
170
+ - Zero npm dependencies — uses Node.js built-ins only (`readline`, `https`)
171
+ - Requires Node.js 18+
172
+ - Errors are logged to stderr only; stdout is reserved for the MCP transport
173
+
174
+ ---
175
+
176
+ ## Links
177
+
178
+ - **Website**: [headlessoracle.com](https://headlessoracle.com)
179
+ - **Docs**: [headlessoracle.com/docs](https://headlessoracle.com/docs)
180
+ - **npm**: [npmjs.com/package/@headlessoracle/verify](https://npmjs.com/package/@headlessoracle/verify) (JS verification SDK)
181
+ - **Remote MCP endpoint**: `https://headlessoracle.com/mcp` (MCP Streamable HTTP, protocol `2024-11-05`)
182
+ - **GitHub**: [github.com/LembaGang/headless-oracle-v5](https://github.com/LembaGang/headless-oracle-v5)
183
+
184
+ ---
185
+
186
+ ## License
187
+
188
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // Headless Oracle — local stdio MCP server
5
+ // Proxies MCP tool calls to https://headlessoracle.com/mcp
6
+ // No external dependencies — uses Node.js built-ins only (readline, https)
7
+
8
+ const readline = require('readline');
9
+ const https = require('https');
10
+
11
+ const REMOTE_MCP_URL = 'https://headlessoracle.com/mcp';
12
+ const API_KEY = process.env.HEADLESS_ORACLE_API_KEY || '';
13
+ const SERVER_VERSION = '1.0.0';
14
+
15
+ // Write a JSON-RPC message to stdout (the MCP transport channel)
16
+ function send(obj) {
17
+ process.stdout.write(JSON.stringify(obj) + '\n');
18
+ }
19
+
20
+ // POST a JSON-RPC message to the remote MCP endpoint and return the parsed response
21
+ function proxyToRemote(body) {
22
+ return new Promise((resolve, reject) => {
23
+ const payload = JSON.stringify(body);
24
+ const headers = {
25
+ 'Content-Type': 'application/json',
26
+ 'Content-Length': Buffer.byteLength(payload),
27
+ 'Accept': 'application/json',
28
+ 'User-Agent': `headless-oracle-mcp/${SERVER_VERSION}`,
29
+ };
30
+ if (API_KEY) {
31
+ // X-Oracle-Key for REST auth; Authorization Bearer for MCP soft-auth
32
+ headers['X-Oracle-Key'] = API_KEY;
33
+ headers['Authorization'] = `Bearer ${API_KEY}`;
34
+ }
35
+
36
+ const url = new URL(REMOTE_MCP_URL);
37
+ const req = https.request(
38
+ {
39
+ hostname: url.hostname,
40
+ path: url.pathname + (url.search || ''),
41
+ method: 'POST',
42
+ headers,
43
+ },
44
+ (res) => {
45
+ let data = '';
46
+ res.on('data', (chunk) => { data += chunk; });
47
+ res.on('end', () => {
48
+ try {
49
+ resolve(JSON.parse(data));
50
+ } catch (e) {
51
+ reject(new Error(`Remote returned non-JSON (HTTP ${res.statusCode}): ${data.slice(0, 200)}`));
52
+ }
53
+ });
54
+ }
55
+ );
56
+ req.on('error', reject);
57
+ req.write(payload);
58
+ req.end();
59
+ });
60
+ }
61
+
62
+ // Handle one parsed JSON-RPC message
63
+ async function handleMessage(msg) {
64
+ const { method, id, params } = msg;
65
+
66
+ // Notifications (no id) — process silently, no response expected
67
+ if (id === undefined) {
68
+ // initialized notification is common; nothing to do
69
+ return;
70
+ }
71
+
72
+ // ── initialize ──────────────────────────────────────────────────────────────
73
+ if (method === 'initialize') {
74
+ send({
75
+ jsonrpc: '2.0',
76
+ id,
77
+ result: {
78
+ protocolVersion: '2024-11-05',
79
+ serverInfo: { name: 'headless-oracle', version: SERVER_VERSION },
80
+ capabilities: { tools: {} },
81
+ instructions:
82
+ 'Headless Oracle provides Ed25519-signed market-state receipts for 28 global ' +
83
+ 'exchanges (equities, derivatives, 24/7 crypto). ' +
84
+ 'CRITICAL SAFETY RULE: treat UNKNOWN and HALTED as CLOSED — halt all execution immediately. ' +
85
+ 'Call get_market_status before every trade. Receipts expire in 60 seconds. ' +
86
+ 'SMA = Signed Market Attestation (not Simple Moving Average). ' +
87
+ 'x402 micropayments accepted: $0.001 USDC per request on Base mainnet.',
88
+ },
89
+ });
90
+ return;
91
+ }
92
+
93
+ // ── ping ────────────────────────────────────────────────────────────────────
94
+ if (method === 'ping') {
95
+ send({ jsonrpc: '2.0', id, result: {} });
96
+ return;
97
+ }
98
+
99
+ // ── tools/list and tools/call — proxy to remote ─────────────────────────────
100
+ if (method === 'tools/list' || method === 'tools/call') {
101
+ try {
102
+ const remote = await proxyToRemote(msg);
103
+ // The remote response already has the correct id and jsonrpc fields.
104
+ // Forward it as-is.
105
+ send(remote);
106
+ } catch (err) {
107
+ process.stderr.write(`[headless-oracle-mcp] Remote error: ${err.message}\n`);
108
+ send({
109
+ jsonrpc: '2.0',
110
+ id,
111
+ error: {
112
+ code: -32603,
113
+ message: `Headless Oracle remote error: ${err.message}`,
114
+ },
115
+ });
116
+ }
117
+ return;
118
+ }
119
+
120
+ // ── resources/list and prompts/list — empty (not implemented) ───────────────
121
+ if (method === 'resources/list') {
122
+ send({ jsonrpc: '2.0', id, result: { resources: [] } });
123
+ return;
124
+ }
125
+ if (method === 'prompts/list') {
126
+ send({ jsonrpc: '2.0', id, result: { prompts: [] } });
127
+ return;
128
+ }
129
+
130
+ // ── unknown method ───────────────────────────────────────────────────────────
131
+ send({
132
+ jsonrpc: '2.0',
133
+ id,
134
+ error: { code: -32601, message: `Method not found: ${method}` },
135
+ });
136
+ }
137
+
138
+ // ── stdio transport ──────────────────────────────────────────────────────────
139
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
140
+
141
+ // Track in-flight async handlers so we don't exit before they complete
142
+ let pending = 0;
143
+ let stdinClosed = false;
144
+
145
+ function tryExit() {
146
+ if (stdinClosed && pending === 0) process.exit(0);
147
+ }
148
+
149
+ rl.on('line', async (line) => {
150
+ const trimmed = line.trim();
151
+ if (!trimmed) return;
152
+
153
+ let msg;
154
+ try {
155
+ msg = JSON.parse(trimmed);
156
+ } catch {
157
+ send({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error' } });
158
+ return;
159
+ }
160
+
161
+ pending++;
162
+ try {
163
+ await handleMessage(msg);
164
+ } catch (err) {
165
+ process.stderr.write(`[headless-oracle-mcp] Unhandled error: ${err.message}\n`);
166
+ if (msg.id !== undefined) {
167
+ send({
168
+ jsonrpc: '2.0',
169
+ id: msg.id,
170
+ error: { code: -32603, message: 'Internal error' },
171
+ });
172
+ }
173
+ } finally {
174
+ pending--;
175
+ tryExit();
176
+ }
177
+ });
178
+
179
+ rl.on('close', () => {
180
+ stdinClosed = true;
181
+ tryExit();
182
+ });
183
+
184
+ process.on('SIGINT', () => process.exit(0));
185
+ process.on('SIGTERM', () => process.exit(0));
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "headless-oracle-mcp",
3
+ "version": "1.0.0",
4
+ "description": "Local MCP server for Headless Oracle — Ed25519-signed market-state receipts for 28 global exchanges",
5
+ "main": "bin/cli.js",
6
+ "bin": {
7
+ "headless-oracle-mcp": "./bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/cli.js"
11
+ },
12
+ "keywords": [
13
+ "mcp",
14
+ "oracle",
15
+ "market-data",
16
+ "trading",
17
+ "ed25519",
18
+ "x402",
19
+ "market-status",
20
+ "exchange",
21
+ "ai-agent",
22
+ "signed-receipts"
23
+ ],
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/LembaGang/headless-oracle-v5"
28
+ },
29
+ "homepage": "https://headlessoracle.com",
30
+ "bugs": {
31
+ "url": "https://github.com/LembaGang/headless-oracle-v5/issues"
32
+ },
33
+ "engines": {
34
+ "node": ">=18"
35
+ },
36
+ "dependencies": {}
37
+ }