-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathserver.js
More file actions
89 lines (72 loc) · 2.63 KB
/
Copy pathserver.js
File metadata and controls
89 lines (72 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env node
/**
* Perspective AI MCP Extension
*
* - Proxy mode (default): forwards stdio to the remote MCP endpoint when
* PERSPECTIVE_ACCESS_TOKEN is set.
* - Catalog mode (MCP_CATALOG_MODE=1): serves the static tool list from
* manifest.json without any network calls. Used by directory checks
* (e.g., Glama) that introspect servers without an access token.
*/
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
const ACCESS_TOKEN = process.env.PERSPECTIVE_ACCESS_TOKEN;
const SERVER_URL = process.env.PERSPECTIVE_SERVER_URL || "https://getperspective.ai/mcp";
const CATALOG_MODE = process.env.MCP_CATALOG_MODE === "1";
if (CATALOG_MODE) {
runCatalog().catch(() => process.exit(1));
} else if (!ACCESS_TOKEN) {
console.error("PERSPECTIVE_ACCESS_TOKEN is required");
process.exit(1);
} else {
runProxy().catch(() => process.exit(1));
}
async function runCatalog() {
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
const {
ListToolsRequestSchema,
CallToolRequestSchema,
} = require("@modelcontextprotocol/sdk/types.js");
const manifest = require("./manifest.json");
const server = new Server(
{ name: manifest.name, version: manifest.version },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: (manifest.tools || []).map((t) => ({
name: t.name,
description: t.description,
inputSchema: { type: "object" },
})),
}));
server.setRequestHandler(CallToolRequestSchema, async () => ({
content: [
{
type: "text",
text: "Tool calls require an access token. Configure PERSPECTIVE_ACCESS_TOKEN or connect via https://getperspective.ai/mcp.",
},
],
isError: true,
}));
await server.connect(new StdioServerTransport());
}
async function runProxy() {
const { StreamableHTTPClientTransport } = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
const localTransport = new StdioServerTransport();
let remoteTransport = null;
localTransport.onmessage = async (message) => {
if (!remoteTransport) {
remoteTransport = new StreamableHTTPClientTransport(new URL(SERVER_URL), {
requestInit: { headers: { Authorization: `Bearer ${ACCESS_TOKEN}` } },
});
remoteTransport.onmessage = (response) => localTransport.send(response);
remoteTransport.onclose = () => process.exit(0);
await remoteTransport.start();
}
await remoteTransport.send(message);
};
localTransport.onclose = () => {
remoteTransport?.close();
process.exit(0);
};
await localTransport.start();
}