json-object-editor 0.10.503 → 0.10.504
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/CHANGELOG.md +7 -0
- package/_www/mcp-export.html +45 -2
- package/_www/mcp-test.html +7 -0
- package/package.json +1 -1
- package/readme.md +4 -1
- package/server/modules/MCP.js +7 -4
- package/server/modules/Server.js +55 -0
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,13 @@
|
|
|
22
22
|
- Hydrate includes full core field definitions from server/fields/core.js (not just names)
|
|
23
23
|
- Manifest now includes { joe: { name, version, hostname } }; mcp-test shows this
|
|
24
24
|
|
|
25
|
+
504 - Secure test pages + shared nav
|
|
26
|
+
- Secured /mcp-test.html and /mcp-export.html with standard JOE auth (root and JOEPATH paths)
|
|
27
|
+
- Added shared top nav between MCP Test and MCP Export pages
|
|
28
|
+
- MCP Export shows instance info (name/version/host) from manifest
|
|
29
|
+
- Added privacy_policy_url and terms_of_service_url to manifest; added public /privacy and /terms pages
|
|
30
|
+
- New Setting: PRIVACY_CONTACT used for contact email on /privacy and /terms
|
|
31
|
+
|
|
25
32
|
### 0.10.500
|
|
26
33
|
500 - MCP integration (initial)
|
|
27
34
|
- MCP core module with JSON-RPC 2.0 endpoint (/mcp) protected by auth
|
package/_www/mcp-export.html
CHANGED
|
@@ -19,9 +19,18 @@
|
|
|
19
19
|
</style>
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
|
+
<nav style="display:flex;gap:10px;align-items:center;margin-bottom:8px">
|
|
23
|
+
<a href="/mcp-test.html">MCP Test</a>
|
|
24
|
+
<a href="/mcp-export.html">MCP Export</a>
|
|
25
|
+
<span style="margin-left:auto"></span>
|
|
26
|
+
<a href="/privacy" target="privacy_win" rel="noopener">Privacy</a>
|
|
27
|
+
<a href="/terms" target="terms_win" rel="noopener">Terms</a>
|
|
28
|
+
</nav>
|
|
22
29
|
<h1>JOE MCP → Assistant Config Export</h1>
|
|
23
30
|
<div class="small">Generate copy/paste config for Custom GPT Actions (OpenAPI) and Assistants (tools array).</div>
|
|
24
31
|
|
|
32
|
+
<pre id="instanceInfo" class="small">Loading instance info…</pre>
|
|
33
|
+
|
|
25
34
|
<div class="grid">
|
|
26
35
|
<section>
|
|
27
36
|
<h3>1) Server</h3>
|
|
@@ -57,7 +66,13 @@
|
|
|
57
66
|
</section>
|
|
58
67
|
|
|
59
68
|
<section>
|
|
60
|
-
<h3>4)
|
|
69
|
+
<h3>4) Starter Agent Instructions</h3>
|
|
70
|
+
<div class="small">Copy into your Custom GPT or Assistant system prompt. Keep it brief and expand as needed.</div>
|
|
71
|
+
<textarea id="starter" readonly></textarea>
|
|
72
|
+
</section>
|
|
73
|
+
|
|
74
|
+
<section>
|
|
75
|
+
<h3>5) JSON-RPC request template</h3>
|
|
61
76
|
<div class="small">When the Assistant calls a tool, POST this body to <code>/mcp</code>.</div>
|
|
62
77
|
<pre>{
|
|
63
78
|
"jsonrpc": "2.0",
|
|
@@ -110,7 +125,7 @@
|
|
|
110
125
|
|
|
111
126
|
const schema = {
|
|
112
127
|
openapi: '3.1.0',
|
|
113
|
-
info: { title: 'JOE MCP Bridge', version: '1.0.0' },
|
|
128
|
+
info: { title: 'JOE MCP Bridge — ' + ((manifest.joe&&manifest.joe.name)||'JOE'), version: '1.0.0' },
|
|
114
129
|
servers: [{ url: serverUrl.replace(/\/$/,'') }],
|
|
115
130
|
paths: {
|
|
116
131
|
'/mcp': {
|
|
@@ -162,6 +177,9 @@
|
|
|
162
177
|
|
|
163
178
|
const url = base.value.replace(/\/$/,'') + manifestPath.value;
|
|
164
179
|
const manifest = await fetchJSON(url);
|
|
180
|
+
if (manifest.joe){
|
|
181
|
+
$('instanceInfo').textContent = `Name: ${manifest.joe.name}\nVersion: ${manifest.joe.version}\nHost: ${manifest.joe.hostname}`;
|
|
182
|
+
}
|
|
165
183
|
manifestOut.style.display='block';
|
|
166
184
|
manifestOut.textContent = JSON.stringify(manifest, null, 2);
|
|
167
185
|
|
|
@@ -171,6 +189,31 @@
|
|
|
171
189
|
const openapi = buildOpenAPI(manifest, base.value);
|
|
172
190
|
openapiEl.value = JSON.stringify(openapi, null, 2);
|
|
173
191
|
|
|
192
|
+
// Starter prompt
|
|
193
|
+
const joeName = (manifest.joe && manifest.joe.name) || 'JOE';
|
|
194
|
+
const starter = [
|
|
195
|
+
`You are a data assistant for ${joeName} (JOE). Use only the provided tools.`,
|
|
196
|
+
'',
|
|
197
|
+
'Workflow:',
|
|
198
|
+
'1) hydrate {} to see core field definitions, schemas, statuses, tags.',
|
|
199
|
+
'2) listSchemas {} and getSchema { "name": "<schema>" } for field shapes.',
|
|
200
|
+
'3) search { "query": { "itemtype": "<schema>" }, "limit": 10 } (cache).',
|
|
201
|
+
' Use { "source": "storage" } when results must be authoritative.',
|
|
202
|
+
'4) getObject { "_id": "<id>", "schema": "<schema>" } for a single item.',
|
|
203
|
+
'5) saveObject only on explicit user request; reflect changes and confirm first.',
|
|
204
|
+
'',
|
|
205
|
+
'Defaults:',
|
|
206
|
+
'- search: cache by default; keep limits small (10–25).',
|
|
207
|
+
'- flatten is optional and off by default; enable only if you need expanded refs.',
|
|
208
|
+
'',
|
|
209
|
+
'Examples:',
|
|
210
|
+
'- listSchemas {}',
|
|
211
|
+
'- getSchema { "name": "client" }',
|
|
212
|
+
'- search { "schema": "client", "source": "storage", "query": { "status": "active" }, "limit": 10 }',
|
|
213
|
+
'- getObject { "_id": "123", "schema": "client" }'
|
|
214
|
+
].join('\n');
|
|
215
|
+
$('starter').value = starter;
|
|
216
|
+
|
|
174
217
|
setStatus('Manifest loaded. Config generated.', true);
|
|
175
218
|
}catch(e){
|
|
176
219
|
setStatus(e.message||String(e), false);
|
package/_www/mcp-test.html
CHANGED
|
@@ -17,6 +17,13 @@
|
|
|
17
17
|
</style>
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
|
+
<nav style="display:flex;gap:10px;align-items:center;margin-bottom:8px">
|
|
21
|
+
<a href="/mcp-test.html">MCP Test</a>
|
|
22
|
+
<a href="/mcp-export.html">MCP Export</a>
|
|
23
|
+
<span style="margin-left:auto"></span>
|
|
24
|
+
<a href="/privacy" target="privacy_win" rel="noopener">Privacy</a>
|
|
25
|
+
<a href="/terms" target="terms_win" rel="noopener">Terms</a>
|
|
26
|
+
</nav>
|
|
20
27
|
<h1>JOE MCP Test</h1>
|
|
21
28
|
<div class="small">Use this page to discover tools and call the JSON-RPC endpoint.</div>
|
|
22
29
|
<pre id="instanceInfo" class="small">Loading instance info…</pre>
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -31,6 +31,8 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
31
31
|
- Endpoints
|
|
32
32
|
- Manifest (public): `GET /.well-known/mcp/manifest.json`
|
|
33
33
|
- JSON-RPC (auth): `POST /mcp`
|
|
34
|
+
- Privacy (public): `/privacy` (uses Setting `PRIVACY_CONTACT` for contact email)
|
|
35
|
+
- Terms (public): `/terms`
|
|
34
36
|
|
|
35
37
|
- Auth
|
|
36
38
|
- If users exist, `POST /mcp` requires cookie or Basic Auth (same as other APIs). If no users configured, it is effectively open.
|
|
@@ -42,7 +44,7 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
42
44
|
|
|
43
45
|
- Tools
|
|
44
46
|
- `listSchemas(name?)`, `getSchema(name)`
|
|
45
|
-
- `getObject(_id, schema?)` (
|
|
47
|
+
- `getObject(_id, schema?)` (supports optional `flatten` and `depth`)
|
|
46
48
|
- `search` (preferred): unified tool for cache and storage
|
|
47
49
|
- Params: `{ schema?, query?, ids?, source?: 'cache'|'storage', limit?, flatten?, depth? }`
|
|
48
50
|
- Defaults to cache across all collections; add `schema` to filter; set `source:"storage"` to query a specific schema in the DB.
|
|
@@ -117,6 +119,7 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
117
119
|
|
|
118
120
|
- Troubleshooting
|
|
119
121
|
- If you see a payload like `{ originalURL: "/...", site: "no site found" }`, the request hit the Sites catch-all. Ensure MCP routes are initialized before Sites (handled by default in `server/init.js` via `MCP.init()`), and use the correct URL: `/.well-known/mcp/manifest.json` or `/mcp`.
|
|
122
|
+
- To update contact email on /privacy and /terms, set Setting `PRIVACY_CONTACT`.
|
|
120
123
|
|
|
121
124
|
## SERVER/PLATFORM mode
|
|
122
125
|
check port 2099
|
package/server/modules/MCP.js
CHANGED
|
@@ -63,7 +63,7 @@ MCP.tools = {
|
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
// Convenience: fetch a single object by _id (schema optional). Prefer cache; fallback to storage.
|
|
66
|
-
getObject: async ({ _id, schema, flatten =
|
|
66
|
+
getObject: async ({ _id, schema, flatten = false, depth = 1 }, _ctx) => {
|
|
67
67
|
if (!_id) throw new Error("Missing required param '_id'");
|
|
68
68
|
// Fast path via global lookup
|
|
69
69
|
let obj = (JOE && JOE.Cache && JOE.Cache.findByID) ? (JOE.Cache.findByID(_id) || null) : null;
|
|
@@ -185,11 +185,11 @@ MCP.tools = {
|
|
|
185
185
|
MCP.descriptions = {
|
|
186
186
|
listSchemas: "List all available JOE schema names.",
|
|
187
187
|
getSchema: "Retrieve a full schema definition by name.",
|
|
188
|
-
getObject: "Fetch a single object by _id (schema optional).
|
|
188
|
+
getObject: "Fetch a single object by _id (schema optional). Supports optional flatten.",
|
|
189
189
|
// getObjectsByIds: "Deprecated - use 'search' with ids.",
|
|
190
190
|
// queryObjects: "Deprecated - use 'search'.",
|
|
191
191
|
// searchCache: "Deprecated - use 'search'.",
|
|
192
|
-
search: "Unified search. Defaults to cache; set source=storage to query DB.",
|
|
192
|
+
search: "Unified search. Defaults to cache; set source=storage to query DB. Flatten is optional (false by default).",
|
|
193
193
|
saveObject: "Create/update an object; triggers events/history.",
|
|
194
194
|
hydrate: "Describe core fields, statuses, tags, and inferred field shapes for an optional schema."
|
|
195
195
|
};
|
|
@@ -278,7 +278,10 @@ MCP.manifest = async function (req, res) {
|
|
|
278
278
|
version: (JOE && JOE.VERSION) || '',
|
|
279
279
|
hostname: (JOE && JOE.webconfig && JOE.webconfig.hostname) || ''
|
|
280
280
|
};
|
|
281
|
-
|
|
281
|
+
const base = req.protocol+':'+(req.get('host')||'');
|
|
282
|
+
const privacyUrl = base+'/'+'privacy';
|
|
283
|
+
const termsUrl = base+'/'+'terms';
|
|
284
|
+
return res.json({ version: "1.0", joe, privacy_policy_url: privacyUrl, terms_of_service_url: termsUrl, tools });
|
|
282
285
|
} catch (e) {
|
|
283
286
|
console.log('[MCP] manifest error:', e);
|
|
284
287
|
return res.status(500).json({ error: e.message || 'manifest error' });
|
package/server/modules/Server.js
CHANGED
|
@@ -104,6 +104,61 @@ server.use(function(req, res, next) {
|
|
|
104
104
|
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
|
105
105
|
next();
|
|
106
106
|
});
|
|
107
|
+
// Public Privacy & Terms pages
|
|
108
|
+
server.get(['/privacy','/privacy-policy'],function(req,res){
|
|
109
|
+
const host = req.protocol+'://'+req.get('host');
|
|
110
|
+
const name = (JOE && JOE.webconfig && JOE.webconfig.name) || 'JOE';
|
|
111
|
+
const updated = new Date().toISOString().split('T')[0];
|
|
112
|
+
const contact = (JOE && JOE.Utils && JOE.Utils.Settings && JOE.Utils.Settings('PRIVACY_CONTACT')) || 'admin@example.com';
|
|
113
|
+
res.send(`
|
|
114
|
+
<!doctype html>
|
|
115
|
+
<html><head><meta charset="utf-8"><title>Privacy Policy - ${name}</title></head>
|
|
116
|
+
<body style="font-family:system-ui,Segoe UI,Roboto,Arial,sans-serif;padding:20px;max-width:900px;line-height:1.6">
|
|
117
|
+
<h1>Privacy Policy for JOE MCP Interface</h1>
|
|
118
|
+
<p><em>Last updated: ${updated}</em></p>
|
|
119
|
+
<h3>Data Processed</h3>
|
|
120
|
+
<p>The JOE MCP interface allows AI systems to retrieve structured data from the JOE platform, such as schemas, objects, and metadata. It does not store, sell, or share personal data.</p>
|
|
121
|
+
<h3>Data Sources</h3>
|
|
122
|
+
<p>All information returned by this interface comes from the JOE instance it’s connected to (${host}). Access to internal data is subject to your JOE configuration and authentication.</p>
|
|
123
|
+
<h3>Third-Party Access</h3>
|
|
124
|
+
<p>This API may be called by authorized OpenAI models or assistants when configured by a verified user. Calls are only executed when explicitly invoked as part of an agent’s reasoning process.</p>
|
|
125
|
+
<h3>Logging</h3>
|
|
126
|
+
<p>Standard request logs (timestamps, method calls, and errors) may be recorded for security and debugging. Logs do not include object contents or personal data.</p>
|
|
127
|
+
<h3>Security</h3>
|
|
128
|
+
<p>All connections are made over HTTPS. No credentials or session tokens are shared with external systems.</p>
|
|
129
|
+
<h3>Contact</h3>
|
|
130
|
+
<p>For privacy concerns, contact ${contact}.</p>
|
|
131
|
+
</body></html>`);
|
|
132
|
+
});
|
|
133
|
+
server.get(['/terms','/terms-of-service'],function(req,res){
|
|
134
|
+
const host = req.protocol+'://'+req.get('host');
|
|
135
|
+
const name = (JOE && JOE.webconfig && JOE.webconfig.name) || 'JOE';
|
|
136
|
+
const updated = new Date().toISOString().split('T')[0];
|
|
137
|
+
const contact = (JOE && JOE.Utils && JOE.Utils.Settings && JOE.Utils.Settings('PRIVACY_CONTACT')) || 'admin@example.com';
|
|
138
|
+
res.send(`
|
|
139
|
+
<!doctype html>
|
|
140
|
+
<html><head><meta charset="utf-8"><title>Terms of Service - ${name}</title></head>
|
|
141
|
+
<body style="font-family:system-ui,Segoe UI,Roboto,Arial,sans-serif;padding:20px;max-width:900px;line-height:1.6">
|
|
142
|
+
<h1>Terms of Service for JOE MCP Interface</h1>
|
|
143
|
+
<p><em>Last updated: ${updated}</em></p>
|
|
144
|
+
<p>Use of this interface implies consent to log and process structured data requests for schema and object retrieval purposes. Access is governed by your JOE configuration and authentication. Do not submit sensitive data unless you are authorized to do so.</p>
|
|
145
|
+
<p>For questions, contact ${contact}.</p>
|
|
146
|
+
</body></html>`);
|
|
147
|
+
});
|
|
148
|
+
// Secure MCP test/export pages with standard auth (root and JOEPATH paths)
|
|
149
|
+
server.get('/mcp-test.html',auth,function(req,res){
|
|
150
|
+
res.sendFile(path.join(JOE.joedir,'_www','mcp-test.html'));
|
|
151
|
+
});
|
|
152
|
+
server.get('/mcp-export.html',auth,function(req,res){
|
|
153
|
+
res.sendFile(path.join(JOE.joedir,'_www','mcp-export.html'));
|
|
154
|
+
});
|
|
155
|
+
server.get(JOE.webconfig.joepath+'_www/mcp-test.html',auth,function(req,res){
|
|
156
|
+
res.sendFile(path.join(JOE.joedir,'_www','mcp-test.html'));
|
|
157
|
+
});
|
|
158
|
+
server.get(JOE.webconfig.joepath+'_www/mcp-export.html',auth,function(req,res){
|
|
159
|
+
res.sendFile(path.join(JOE.joedir,'_www','mcp-export.html'));
|
|
160
|
+
});
|
|
161
|
+
|
|
107
162
|
server.use(JOE.webconfig.joepath,express.static(JOE.joedir));
|
|
108
163
|
|
|
109
164
|
//USER
|