openvibers/openvibe.search Commits
agent.json names the MCP server and OpenAPI document Search already serves (AGT-2) (#213)
Changes
@@@ -1,7 +1,9 @@'use strict';// What search.openvibe.network tells an agent about itself (openvibe-shared/agent-layer): /.well-known/agent.json.// The public pages are the search page (front, and results for anonymous callers) and the update log; the JSON--// API is /api/v1. No separate documentation page, OpenAPI document or MCP endpoint is published, so none is named.++// API is /api/v1, its OpenAPI 3.1 document is /openapi.json (server/openapi.js), and the Search Fabric is an MCP server++// at /mcp (server/api/mcp.js: two read-only tools, anonymous or with a Network token). No separate documentation page++// is published, so none is named.module.exports = {id: 'search',name: 'OpenVibe.Search',@@@ -9,6 +11,8 @@ module.exports = {home: 'https://search.openvibe.network',site: 'search.openvibe.network',api: '/api/v1',++ openapi: '/openapi.json',++ mcp: { url: '/mcp' },policy: {auth: ['none', 'Network OIDC'],rateLimit: '120 read API requests a minute and 3,000 an hour per caller; the Search Fabric query 30 a minute and 600 an hour; the HTML page follows nginx\'s address limits',@@@ -130,6 +130,12 @@ t('the agent layer: manifest, twins, and the pages that name them', async () =>assert.strictEqual(d.home, 'https://search.openvibe.network');assert.strictEqual(d.api, 'https://search.openvibe.network/api/v1');assert.deepStrictEqual(d.policy.auth, ['none', 'Network OIDC']);++ // The OpenAPI document and the MCP server it names are the ones this service answers (AGT-2).++ assert.strictEqual(d.openapi, 'https://search.openvibe.network/openapi.json');++ assert.deepStrictEqual([d.mcp.url, d.mcp.transport], ['https://search.openvibe.network/mcp', 'streamable-http']);++ const init = await request(svc.base, 'POST', '/mcp', { body: { jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-06-18', capabilities: {}, clientInfo: { name: 'test', version: '1' } } } });++ assert.strictEqual(init.status, 200, 'the named MCP endpoint answers an initialize');++ assert.ok(/"protocolVersion"/.test(init.text));// A twin of the front page and of the update log, from the pages' own render. The twin's canonical is the// manifest's home (the site's public address), not the test server's own base URL.for (const [p, canonical] of [['/index.md', 'https://search.openvibe.network/'], ['/updates.md', 'https://search.openvibe.network/updates']]) {
@@ -1,7 +1,9 @@
@@ -1,7 +1,9 @@
'use strict';
'use strict';
// What search.openvibe.network tells an agent about itself (openvibe-shared/agent-layer): /.well-known/agent.json.
// What search.openvibe.network tells an agent about itself (openvibe-shared/agent-layer): /.well-known/agent.json.
// The public pages are the search page (front, and results for anonymous callers) and the update log; the JSON
// The public pages are the search page (front, and results for anonymous callers) and the update log; the JSON
-// API is /api/v1. No separate documentation page, OpenAPI document or MCP endpoint is published, so none is named.
+// API is /api/v1, its OpenAPI 3.1 document is /openapi.json (server/openapi.js), and the Search Fabric is an MCP server
+// at /mcp (server/api/mcp.js: two read-only tools, anonymous or with a Network token). No separate documentation page
+// is published, so none is named.
module.exports = {
module.exports = {
id: 'search',
id: 'search',
name: 'OpenVibe.Search',
name: 'OpenVibe.Search',
@@ -9,6 +11,8 @@ module.exports = {
@@ -9,6 +11,8 @@ module.exports = {
home: 'https://search.openvibe.network',
home: 'https://search.openvibe.network',
site: 'search.openvibe.network',
site: 'search.openvibe.network',
api: '/api/v1',
api: '/api/v1',
+ openapi: '/openapi.json',
+ mcp: { url: '/mcp' },
policy: {
policy: {
auth: ['none', 'Network OIDC'],
auth: ['none', 'Network OIDC'],
rateLimit: '120 read API requests a minute and 3,000 an hour per caller; the Search Fabric query 30 a minute and 600 an hour; the HTML page follows nginx\'s address limits',
rateLimit: '120 read API requests a minute and 3,000 an hour per caller; the Search Fabric query 30 a minute and 600 an hour; the HTML page follows nginx\'s address limits',
@@ -130,6 +130,12 @@ t('the agent layer: manifest, twins, and the pages that name them', async () =>
@@ -130,6 +130,12 @@ t('the agent layer: manifest, twins, and the pages that name them', async () =>
assert.strictEqual(d.home, 'https://search.openvibe.network');
assert.strictEqual(d.home, 'https://search.openvibe.network');
assert.strictEqual(d.api, 'https://search.openvibe.network/api/v1');
assert.strictEqual(d.api, 'https://search.openvibe.network/api/v1');
assert.deepStrictEqual(d.policy.auth, ['none', 'Network OIDC']);
assert.deepStrictEqual(d.policy.auth, ['none', 'Network OIDC']);
+ // The OpenAPI document and the MCP server it names are the ones this service answers (AGT-2).
+ assert.strictEqual(d.openapi, 'https://search.openvibe.network/openapi.json');
+ assert.deepStrictEqual([d.mcp.url, d.mcp.transport], ['https://search.openvibe.network/mcp', 'streamable-http']);
+ const init = await request(svc.base, 'POST', '/mcp', { body: { jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-06-18', capabilities: {}, clientInfo: { name: 'test', version: '1' } } } });
+ assert.strictEqual(init.status, 200, 'the named MCP endpoint answers an initialize');
+ assert.ok(/"protocolVersion"/.test(init.text));
// A twin of the front page and of the update log, from the pages' own render. The twin's canonical is the
// A twin of the front page and of the update log, from the pages' own render. The twin's canonical is the
// manifest's home (the site's public address), not the test server's own base URL.
// manifest's home (the site's public address), not the test server's own base URL.
for (const [p, canonical] of [['/index.md', 'https://search.openvibe.network/'], ['/updates.md', 'https://search.openvibe.network/updates']]) {
for (const [p, canonical] of [['/index.md', 'https://search.openvibe.network/'], ['/updates.md', 'https://search.openvibe.network/updates']]) {