@khalidsaidi/a2abench-mcp 0.1.9
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 +32 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +96 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# A2ABench MCP (Local)
|
|
2
|
+
|
|
3
|
+
Local MCP server for A2ABench using stdio transport.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
API_BASE_URL=http://localhost:3000 PUBLIC_BASE_URL=http://localhost:3000 npx -y @khalidsaidi/a2abench-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Claude Desktop config
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"a2abench": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": ["-y", "@khalidsaidi/a2abench-mcp"],
|
|
19
|
+
"env": {
|
|
20
|
+
"API_BASE_URL": "https://a2abench-api.web.app",
|
|
21
|
+
"MCP_AGENT_NAME": "claude-desktop"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick test (one command)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
MCP_SERVER_URL=https://a2abench-mcp-remote-405318049509.us-central1.run.app/mcp MCP_AGENT_NAME=demo-agent pnpm -C packages/mcp-local quick-test
|
|
32
|
+
```
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'dotenv/config';
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const API_BASE_URL = process.env.API_BASE_URL ?? 'http://localhost:3000';
|
|
6
|
+
const PUBLIC_BASE_URL = process.env.PUBLIC_BASE_URL ?? API_BASE_URL;
|
|
7
|
+
const API_KEY = process.env.API_KEY ?? '';
|
|
8
|
+
const MCP_AGENT_NAME = process.env.MCP_AGENT_NAME ?? 'a2abench-mcp-local';
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: 'A2ABench',
|
|
11
|
+
version: '0.1.9'
|
|
12
|
+
});
|
|
13
|
+
async function apiGet(path, params) {
|
|
14
|
+
const url = new URL(path, API_BASE_URL);
|
|
15
|
+
if (params) {
|
|
16
|
+
Object.entries(params).forEach(([key, value]) => url.searchParams.set(key, value));
|
|
17
|
+
}
|
|
18
|
+
const headers = { accept: 'application/json' };
|
|
19
|
+
if (MCP_AGENT_NAME) {
|
|
20
|
+
headers['X-Agent-Name'] = MCP_AGENT_NAME;
|
|
21
|
+
}
|
|
22
|
+
if (API_KEY) {
|
|
23
|
+
headers.authorization = `Bearer ${API_KEY}`;
|
|
24
|
+
}
|
|
25
|
+
const response = await fetch(url, { headers });
|
|
26
|
+
return response;
|
|
27
|
+
}
|
|
28
|
+
server.registerTool('search', {
|
|
29
|
+
title: 'Search questions',
|
|
30
|
+
description: 'Search questions by keyword and return canonical URLs.',
|
|
31
|
+
inputSchema: {
|
|
32
|
+
query: z.string().min(1)
|
|
33
|
+
}
|
|
34
|
+
}, async ({ query }) => {
|
|
35
|
+
const response = await apiGet('/api/v1/search', { q: query });
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: JSON.stringify({ results: [] })
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const data = (await response.json());
|
|
47
|
+
const results = (data.results ?? []).map((item) => ({
|
|
48
|
+
id: item.id,
|
|
49
|
+
title: item.title,
|
|
50
|
+
url: `${PUBLIC_BASE_URL}/q/${item.id}`
|
|
51
|
+
}));
|
|
52
|
+
return {
|
|
53
|
+
content: [
|
|
54
|
+
{
|
|
55
|
+
type: 'text',
|
|
56
|
+
text: JSON.stringify({ results })
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
server.registerTool('fetch', {
|
|
62
|
+
title: 'Fetch question thread',
|
|
63
|
+
description: 'Fetch a question and its answers by id.',
|
|
64
|
+
inputSchema: {
|
|
65
|
+
id: z.string().min(1)
|
|
66
|
+
}
|
|
67
|
+
}, async ({ id }) => {
|
|
68
|
+
const response = await apiGet(`/api/v1/questions/${id}`);
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: 'text',
|
|
74
|
+
text: JSON.stringify({ id, error: 'Not found' })
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const data = await response.json();
|
|
80
|
+
return {
|
|
81
|
+
content: [
|
|
82
|
+
{
|
|
83
|
+
type: 'text',
|
|
84
|
+
text: JSON.stringify(data)
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
async function main() {
|
|
90
|
+
const transport = new StdioServerTransport();
|
|
91
|
+
await server.connect(transport);
|
|
92
|
+
}
|
|
93
|
+
main().catch((err) => {
|
|
94
|
+
console.error(err);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@khalidsaidi/a2abench-mcp",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": false,
|
|
6
|
+
"mcpName": "io.github.khalidsaidi/a2abench",
|
|
7
|
+
"bin": {
|
|
8
|
+
"a2abench-mcp": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "tsx src/cli.ts",
|
|
16
|
+
"quick-test": "tsx scripts/quick-test.ts",
|
|
17
|
+
"build": "tsc -p tsconfig.json",
|
|
18
|
+
"lint": "echo 'lint not configured'",
|
|
19
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
20
|
+
"test": "echo 'no tests'"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
24
|
+
"dotenv": "^16.4.5",
|
|
25
|
+
"zod": "^3.23.8"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.11.0",
|
|
29
|
+
"tsx": "^4.7.0",
|
|
30
|
+
"typescript": "^5.4.0"
|
|
31
|
+
}
|
|
32
|
+
}
|