@pipeworx/mcp-openreview 0.1.0 → 0.1.1

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  OpenReview MCP — ML conference submissions and reviews (API v2)
4
4
 
5
- Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 250+ live data sources.
5
+ Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1163+ live data sources.
6
6
 
7
7
  ## Tools
8
8
 
@@ -13,7 +13,7 @@ Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents
13
13
  | `list_submissions` | Papers submitted to a venue. Pass the venue group id as venue_id. |
14
14
  | `get_note` | Single note — paper, review, comment, decision, etc. |
15
15
  | `get_paper` | Paper + all child notes (reviews, rebuttal, decision, metareview). Pass the forum id (= paper note id). |
16
- | `search_notes` | Full-text search across notes. |
16
+ | `search_notes` | Full-text search across OpenReview notes (papers, reviews, decisions) by query string; optionally restrict to a content field (e.g. title, abstract) or filter by author signature; returns matching note ids, titles, and venues. |
17
17
 
18
18
  ## Quick Start
19
19
 
@@ -29,7 +29,7 @@ Add to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):
29
29
  }
30
30
  ```
31
31
 
32
- Or connect to the full Pipeworx gateway for access to all 250+ data sources:
32
+ Or connect to the full Pipeworx gateway for access to all 1163+ data sources:
33
33
 
34
34
  ```json
35
35
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-openreview",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "OpenReview MCP — ML conference submissions and reviews (API v2)",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/openreview",
4
4
  "title": "Openreview",
5
5
  "description": "OpenReview MCP — ML conference submissions and reviews (API v2)",
6
- "version": "0.1.0",
6
+ "version": "0.1.1",
7
7
  "websiteUrl": "https://pipeworx.io/packs/openreview",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-openreview",
package/src/index.ts CHANGED
@@ -89,7 +89,7 @@ const tools: McpToolExport['tools'] = [
89
89
  },
90
90
  {
91
91
  name: 'search_notes',
92
- description: 'Full-text search across notes.',
92
+ description: 'Full-text search across OpenReview notes (papers, reviews, decisions) by query string; optionally restrict to a content field (e.g. title, abstract) or filter by author signature; returns matching note ids, titles, and venues.',
93
93
  inputSchema: {
94
94
  type: 'object',
95
95
  properties: {
@@ -108,13 +108,17 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
108
108
  const apiKey = (args._apiKey as string | undefined)?.trim();
109
109
  switch (name) {
110
110
  case 'list_venues': {
111
- const params = new URLSearchParams({
112
- prefix: '~',
113
- limit: String(Math.min(1000, Math.max(1, (args.limit as number) ?? 50))),
114
- offset: String(Math.max(0, (args.offset as number) ?? 0)),
115
- });
116
- if (args.query) params.set('regex', String(args.query));
117
- return orGet(apiKey, `/groups?${params}`);
111
+ // The canonical anonymous-accessible venue list is the members array
112
+ // of the "venues" group (~4000 conferences/workshops).
113
+ const data = (await orGet(apiKey, `/groups?id=venues`)) as {
114
+ groups?: { members?: string[] }[];
115
+ };
116
+ const all = data.groups?.[0]?.members ?? [];
117
+ const query = (args.query as string | undefined)?.toLowerCase();
118
+ const filtered = query ? all.filter((id) => id.toLowerCase().includes(query)) : all;
119
+ const offset = Math.max(0, (args.offset as number) ?? 0);
120
+ const limit = Math.min(1000, Math.max(1, (args.limit as number) ?? 50));
121
+ return { total: filtered.length, venues: filtered.slice(offset, offset + limit) };
118
122
  }
119
123
  case 'get_venue':
120
124
  return orGet(apiKey, `/groups?id=${encodeURIComponent(reqStr(args, 'group_id', '"ICLR.cc/2024/Conference"'))}`);
@@ -161,7 +165,10 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
161
165
 
162
166
  async function orGet(apiKey: string | undefined, path: string) {
163
167
  const url = `${BASE}${path}`;
164
- const headers: Record<string, string> = { Accept: 'application/json' };
168
+ // A descriptive User-Agent — OpenReview's edge (Cloudflare) 403s the default
169
+ // Workers fetch UA, which surfaced as "unauthorized" from the gateway even
170
+ // though the endpoint is anonymous (works fine with a UA).
171
+ const headers: Record<string, string> = { Accept: 'application/json', 'User-Agent': 'pipeworx-mcp-openreview/1.0 (+https://pipeworx.io)' };
165
172
  if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
166
173
  const res = await fetch(url, { headers });
167
174
  if (res.status === 401 || res.status === 403) throw new Error('OpenReview: unauthorized');