@spilno/herald-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.
- package/README.md +65 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +226 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @spilno/herald-mcp
|
|
2
|
+
|
|
3
|
+
Herald MCP - Diplomatic interface to [CEDA](https://getceda.com) (Cognitive Event-Driven Architecture).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @spilno/herald-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install globally:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @spilno/herald-mcp
|
|
15
|
+
herald-mcp
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
Set environment variables:
|
|
21
|
+
|
|
22
|
+
| Variable | Required | Description |
|
|
23
|
+
|----------|----------|-------------|
|
|
24
|
+
| `HERALD_API_URL` | Yes | CEDA server URL (e.g., `https://getceda.com`) |
|
|
25
|
+
| `HERALD_API_TOKEN` | No | Bearer token for authentication |
|
|
26
|
+
|
|
27
|
+
## Tools
|
|
28
|
+
|
|
29
|
+
Herald exposes these MCP tools:
|
|
30
|
+
|
|
31
|
+
- **herald_health** - Check CEDA system status
|
|
32
|
+
- **herald_stats** - Get server statistics and pattern info
|
|
33
|
+
- **herald_predict** - Generate structure prediction from natural language
|
|
34
|
+
- **herald_observe** - Record prediction feedback for learning
|
|
35
|
+
|
|
36
|
+
## Usage with Claude Desktop
|
|
37
|
+
|
|
38
|
+
Add to `claude_desktop_config.json`:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"mcpServers": {
|
|
43
|
+
"herald": {
|
|
44
|
+
"command": "npx",
|
|
45
|
+
"args": ["@spilno/herald-mcp"],
|
|
46
|
+
"env": {
|
|
47
|
+
"HERALD_API_URL": "https://getceda.com"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Usage with Devin
|
|
55
|
+
|
|
56
|
+
In Devin MCP marketplace:
|
|
57
|
+
- **Server Name**: Herald-CEDA
|
|
58
|
+
- **Transport**: STDIO
|
|
59
|
+
- **Command**: `npx`
|
|
60
|
+
- **Arguments**: `@spilno/herald-mcp`
|
|
61
|
+
- **Environment**: `HERALD_API_URL=https://getceda.com`
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald MCP - Diplomatic interface to CEDA ecosystem
|
|
4
|
+
*
|
|
5
|
+
* Herald speaks CEDA. Cognition stays sovereign.
|
|
6
|
+
*/
|
|
7
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
// Configuration - all sensitive values from environment only
|
|
11
|
+
const CEDA_API_URL = process.env.HERALD_API_URL;
|
|
12
|
+
const CEDA_API_TOKEN = process.env.HERALD_API_TOKEN; // Bearer token (optional for demo)
|
|
13
|
+
const CEDA_API_USER = process.env.HERALD_API_USER; // Basic auth user (optional)
|
|
14
|
+
const CEDA_API_PASS = process.env.HERALD_API_PASS; // Basic auth pass (optional)
|
|
15
|
+
const DEFAULT_CONTEXT_ID = process.env.HERALD_CONTEXT_ID || "ctx_default";
|
|
16
|
+
// Auth strategy: prefer Bearer token, fallback to Basic auth, allow none for demo
|
|
17
|
+
function getAuthHeader() {
|
|
18
|
+
if (CEDA_API_TOKEN) {
|
|
19
|
+
return `Bearer ${CEDA_API_TOKEN}`;
|
|
20
|
+
}
|
|
21
|
+
if (CEDA_API_USER && CEDA_API_PASS) {
|
|
22
|
+
const basicAuth = Buffer.from(`${CEDA_API_USER}:${CEDA_API_PASS}`).toString("base64");
|
|
23
|
+
return `Basic ${basicAuth}`;
|
|
24
|
+
}
|
|
25
|
+
return null; // No auth - acceptable for local demo
|
|
26
|
+
}
|
|
27
|
+
async function callCedaAPI(endpoint, method = "GET", body) {
|
|
28
|
+
// Validate configuration
|
|
29
|
+
if (!CEDA_API_URL) {
|
|
30
|
+
return {
|
|
31
|
+
success: false,
|
|
32
|
+
error: "HERALD_API_URL not configured. Set environment variable."
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const url = `${CEDA_API_URL}${endpoint}`;
|
|
36
|
+
const headers = {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
};
|
|
39
|
+
// Add auth header if configured (optional for demo)
|
|
40
|
+
const authHeader = getAuthHeader();
|
|
41
|
+
if (authHeader) {
|
|
42
|
+
headers["Authorization"] = authHeader;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const response = await fetch(url, {
|
|
46
|
+
method,
|
|
47
|
+
headers,
|
|
48
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
49
|
+
});
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
return { success: false, error: `HTTP ${response.status}: ${response.statusText}` };
|
|
52
|
+
}
|
|
53
|
+
return await response.json();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return { success: false, error: `Connection failed: ${error}` };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Create MCP server
|
|
60
|
+
const server = new Server({
|
|
61
|
+
name: "herald",
|
|
62
|
+
version: "1.0.0",
|
|
63
|
+
}, {
|
|
64
|
+
capabilities: {
|
|
65
|
+
tools: {},
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
// Tool definitions - aligned with actual CEDA server endpoints
|
|
69
|
+
const tools = [
|
|
70
|
+
{
|
|
71
|
+
name: "herald_health",
|
|
72
|
+
description: "Check Herald and CEDA system status",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: {},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "herald_stats",
|
|
80
|
+
description: "Get CEDA server statistics and loaded patterns info",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "herald_predict",
|
|
88
|
+
description: "Generate non-deterministic structure prediction from signal",
|
|
89
|
+
inputSchema: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
signal: {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: "Natural language input (e.g., 'create safety assessment module')",
|
|
95
|
+
},
|
|
96
|
+
context_id: {
|
|
97
|
+
type: "string",
|
|
98
|
+
description: "Context identifier (user/company)",
|
|
99
|
+
},
|
|
100
|
+
context: {
|
|
101
|
+
type: "string",
|
|
102
|
+
description: "Additional context for better prediction",
|
|
103
|
+
},
|
|
104
|
+
session_id: {
|
|
105
|
+
type: "string",
|
|
106
|
+
description: "Optional session for continuity",
|
|
107
|
+
},
|
|
108
|
+
domain: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "Optional domain filter (e.g., 'hse')",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
required: ["signal"],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "herald_observe",
|
|
118
|
+
description: "Record prediction outcome for learning",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {
|
|
122
|
+
session_id: {
|
|
123
|
+
type: "string",
|
|
124
|
+
description: "Session ID from prediction",
|
|
125
|
+
},
|
|
126
|
+
accepted: {
|
|
127
|
+
type: "boolean",
|
|
128
|
+
description: "Was prediction accepted by user?",
|
|
129
|
+
},
|
|
130
|
+
feedback: {
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "Optional user feedback/comment",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
required: ["session_id", "accepted"],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
// Handle list tools
|
|
140
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
141
|
+
tools,
|
|
142
|
+
}));
|
|
143
|
+
// Handle tool calls
|
|
144
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
145
|
+
const { name, arguments: args } = request.params;
|
|
146
|
+
switch (name) {
|
|
147
|
+
case "herald_health": {
|
|
148
|
+
// Maps to: GET /health
|
|
149
|
+
const result = await callCedaAPI("/health");
|
|
150
|
+
return {
|
|
151
|
+
content: [
|
|
152
|
+
{
|
|
153
|
+
type: "text",
|
|
154
|
+
text: JSON.stringify(result, null, 2),
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
case "herald_stats": {
|
|
160
|
+
// Maps to: GET /api/stats
|
|
161
|
+
const result = await callCedaAPI("/api/stats");
|
|
162
|
+
return {
|
|
163
|
+
content: [
|
|
164
|
+
{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: JSON.stringify(result, null, 2),
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
case "herald_predict": {
|
|
172
|
+
// Maps to: POST /api/predict
|
|
173
|
+
const params = args;
|
|
174
|
+
// Build context array if additional context provided
|
|
175
|
+
const context = params.context ? [
|
|
176
|
+
{
|
|
177
|
+
type: "user_context",
|
|
178
|
+
value: params.context,
|
|
179
|
+
source: "herald_mcp",
|
|
180
|
+
}
|
|
181
|
+
] : [];
|
|
182
|
+
const result = await callCedaAPI("/api/predict", "POST", {
|
|
183
|
+
input: params.signal, // CEDA uses 'input' not 'signal'
|
|
184
|
+
context,
|
|
185
|
+
config: {
|
|
186
|
+
enableAutoFix: true,
|
|
187
|
+
maxAutoFixAttempts: 3,
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
return {
|
|
191
|
+
content: [
|
|
192
|
+
{
|
|
193
|
+
type: "text",
|
|
194
|
+
text: JSON.stringify(result, null, 2),
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
case "herald_observe": {
|
|
200
|
+
// Maps to: POST /api/feedback
|
|
201
|
+
const params = args;
|
|
202
|
+
const result = await callCedaAPI("/api/feedback", "POST", {
|
|
203
|
+
sessionId: params.session_id, // CEDA uses camelCase
|
|
204
|
+
accepted: params.accepted,
|
|
205
|
+
comment: params.feedback,
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
content: [
|
|
209
|
+
{
|
|
210
|
+
type: "text",
|
|
211
|
+
text: JSON.stringify(result, null, 2),
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
default:
|
|
217
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
// Start server
|
|
221
|
+
async function main() {
|
|
222
|
+
const transport = new StdioServerTransport();
|
|
223
|
+
await server.connect(transport);
|
|
224
|
+
console.error("Herald MCP server running on stdio");
|
|
225
|
+
}
|
|
226
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spilno/herald-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Herald MCP - Diplomatic interface to CEDA (Cognitive Event-Driven Architecture)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": "./dist/index.js",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"start": "node dist/index.js",
|
|
11
|
+
"dev": "tsx src/index.ts",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mcp",
|
|
16
|
+
"model-context-protocol",
|
|
17
|
+
"ceda",
|
|
18
|
+
"ai",
|
|
19
|
+
"copilot",
|
|
20
|
+
"herald"
|
|
21
|
+
],
|
|
22
|
+
"author": "Spilno",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/Spilno-me/ceda.git",
|
|
27
|
+
"directory": "herald-mcp"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://getceda.com",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^0.5.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20.0.0",
|
|
35
|
+
"tsx": "^4.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md"
|
|
44
|
+
]
|
|
45
|
+
}
|