@access-mcp/announcements 0.1.0 → 0.2.0
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 +46 -121
- package/dist/index.js +2 -17
- package/dist/server.d.ts +28 -85
- package/dist/server.js +70 -101
- package/package.json +3 -3
- package/src/index.ts +2 -18
- package/src/server.integration.test.ts +63 -72
- package/src/server.test.ts +69 -81
- package/src/server.ts +56 -217
package/README.md
CHANGED
|
@@ -4,166 +4,91 @@ MCP server providing access to ACCESS support announcements, service updates, ma
|
|
|
4
4
|
|
|
5
5
|
## Usage Examples
|
|
6
6
|
|
|
7
|
-
### **
|
|
7
|
+
### **Recent Updates**
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
10
|
+
"Recent ACCESS announcements"
|
|
11
|
+
"Updates from past week"
|
|
12
|
+
"Latest community news"
|
|
13
|
+
"Announcements since January 2024"
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
### **
|
|
16
|
+
### **System & Maintenance**
|
|
17
17
|
|
|
18
18
|
```
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"Tell me about network-related announcements"
|
|
19
|
+
"GPU maintenance announcements"
|
|
20
|
+
"Delta maintenance notices"
|
|
21
|
+
"Bridges-2 system updates"
|
|
22
|
+
"Network-related announcements"
|
|
24
23
|
```
|
|
25
24
|
|
|
26
|
-
### **
|
|
25
|
+
### **By Topic**
|
|
27
26
|
|
|
28
27
|
```
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
### **Track Specific Systems or Communities**
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
"Show me all announcements about Anvil"
|
|
39
|
-
"What updates are there for the CSSN community?"
|
|
40
|
-
"Any news from the Open OnDemand team?"
|
|
41
|
-
"Show me Pegasus-related announcements"
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### **Search by Topic or Technology**
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
"Find announcements about cloud computing"
|
|
48
|
-
"Show me AI and machine learning updates"
|
|
49
|
-
"Any announcements about allocation proposals?"
|
|
50
|
-
"What's new with data science resources?"
|
|
51
|
-
"Find announcements about Python or PyTorch"
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### **Time-Based Searches**
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
"Show me announcements from the past month"
|
|
58
|
-
"What was announced last week?"
|
|
59
|
-
"Find announcements since January 1st, 2024"
|
|
60
|
-
"Show me announcements from the past 6 months"
|
|
28
|
+
"Training workshops announced"
|
|
29
|
+
"Machine learning updates"
|
|
30
|
+
"Cloud computing announcements"
|
|
31
|
+
"Allocation proposal news"
|
|
32
|
+
"Python and PyTorch updates"
|
|
61
33
|
```
|
|
62
34
|
|
|
63
35
|
## Tools
|
|
64
36
|
|
|
65
|
-
###
|
|
37
|
+
### search_announcements
|
|
66
38
|
|
|
67
|
-
Search ACCESS support announcements with
|
|
39
|
+
Search and filter ACCESS support announcements with flexible filtering options.
|
|
68
40
|
|
|
69
41
|
**Parameters:**
|
|
70
42
|
- `tags` - Filter by topics (comma-separated). Examples: 'gpu,nvidia', 'machine-learning,ai', 'training,workshop'
|
|
71
|
-
- `ag` - Filter by system/community group. Examples: '
|
|
72
|
-
- `relative_start_date` - Filter from relative date. Examples: 'today', '-1 week', '-1 month', '-
|
|
43
|
+
- `ag` - Filter by system/community group. Examples: 'Anvil', 'ACCESS Support', 'DARWIN', 'Stampede-3'
|
|
44
|
+
- `relative_start_date` - Filter from relative date. Examples: 'today', '-1 week', '-1 month', '-1 year'
|
|
73
45
|
- `relative_end_date` - Filter to relative date. Examples: 'now', 'today', '-1 week', '+1 week'
|
|
74
46
|
- `start_date` - Filter from exact date (YYYY-MM-DD). Example: '2024-01-01'
|
|
75
47
|
- `end_date` - Filter to exact date (YYYY-MM-DD). Example: '2024-12-31'
|
|
76
|
-
- `limit` - Maximum results (default:
|
|
48
|
+
- `limit` - Maximum results (default: 25). Automatically rounded to valid API page sizes (5, 10, 25, or 50)
|
|
77
49
|
|
|
78
50
|
**Usage Examples:**
|
|
79
51
|
```javascript
|
|
80
|
-
// Recent
|
|
81
|
-
|
|
82
|
-
tags: "gpu,nvidia",
|
|
52
|
+
// Recent announcements
|
|
53
|
+
search_announcements({
|
|
83
54
|
relative_start_date: "-1 month",
|
|
84
55
|
limit: 10
|
|
85
56
|
})
|
|
86
57
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
limit:
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
// Training announcements from the past 3 months
|
|
95
|
-
get_announcements({
|
|
96
|
-
tags: "training,professional-development",
|
|
97
|
-
relative_start_date: "-3 months",
|
|
98
|
-
limit: 20
|
|
58
|
+
// Topic-specific search - GPU announcements
|
|
59
|
+
search_announcements({
|
|
60
|
+
tags: "gpu,nvidia",
|
|
61
|
+
relative_start_date: "-1 year",
|
|
62
|
+
limit: 25
|
|
99
63
|
})
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### get_announcements_by_tags
|
|
103
|
-
|
|
104
|
-
Find announcements about specific topics or systems.
|
|
105
|
-
|
|
106
|
-
**Parameters:**
|
|
107
|
-
- `tags` (required) - Specific topics (comma-separated). Examples: 'gpu,nvidia', 'data-science,python', 'cloud-computing'
|
|
108
|
-
- `limit` - Maximum results (default: 10)
|
|
109
64
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
tags: "machine-learning,ai,deep-learning",
|
|
65
|
+
// System-specific search - Anvil announcements
|
|
66
|
+
search_announcements({
|
|
67
|
+
ag: "Anvil",
|
|
68
|
+
relative_start_date: "-6 months",
|
|
115
69
|
limit: 15
|
|
116
70
|
})
|
|
117
71
|
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
tags: "
|
|
121
|
-
|
|
122
|
-
})
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### get_announcements_by_affinity_group
|
|
126
|
-
|
|
127
|
-
Get announcements for specific ACCESS systems or community groups.
|
|
128
|
-
|
|
129
|
-
**Parameters:**
|
|
130
|
-
- `ag` (required) - System or community name. Examples: 'DELTA', 'Anvil', 'Bridges-2', 'ACCESS Support', 'Open OnDemand'
|
|
131
|
-
- `limit` - Maximum results (default: 10)
|
|
132
|
-
|
|
133
|
-
**Usage Examples:**
|
|
134
|
-
```javascript
|
|
135
|
-
// All DELTA-related announcements
|
|
136
|
-
get_announcements_by_affinity_group({
|
|
137
|
-
ag: "DELTA",
|
|
72
|
+
// Machine learning announcements
|
|
73
|
+
search_announcements({
|
|
74
|
+
tags: "machine-learning,ai",
|
|
75
|
+
relative_start_date: "-1 year",
|
|
138
76
|
limit: 20
|
|
139
77
|
})
|
|
140
78
|
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
ag: "
|
|
79
|
+
// Combined filters - recent announcements for ACCESS Support
|
|
80
|
+
search_announcements({
|
|
81
|
+
ag: "ACCESS Support",
|
|
82
|
+
tags: "maintenance",
|
|
83
|
+
relative_start_date: "-3 months",
|
|
144
84
|
limit: 10
|
|
145
85
|
})
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### get_recent_announcements
|
|
149
|
-
|
|
150
|
-
Get the latest announcements from a recent time period.
|
|
151
86
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
```javascript
|
|
158
|
-
// Past week's announcements
|
|
159
|
-
get_recent_announcements({
|
|
160
|
-
period: "1 week",
|
|
161
|
-
limit: 15
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
// Past 3 months overview
|
|
165
|
-
get_recent_announcements({
|
|
166
|
-
period: "3 months",
|
|
87
|
+
// Exact date range search
|
|
88
|
+
search_announcements({
|
|
89
|
+
tags: "training,professional-development",
|
|
90
|
+
start_date: "2024-01-01",
|
|
91
|
+
end_date: "2024-12-31",
|
|
167
92
|
limit: 25
|
|
168
93
|
})
|
|
169
94
|
```
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { AnnouncementsServer } from "./server.js";
|
|
3
3
|
async function main() {
|
|
4
|
-
// Check if we should run as HTTP server (for deployment)
|
|
5
|
-
const port = process.env.PORT;
|
|
6
4
|
const server = new AnnouncementsServer();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
await server.start({ httpPort: parseInt(port) });
|
|
10
|
-
// Keep the process running in HTTP mode
|
|
11
|
-
process.on('SIGINT', () => {
|
|
12
|
-
console.log('Shutting down server...');
|
|
13
|
-
process.exit(0);
|
|
14
|
-
});
|
|
15
|
-
// Keep the event loop alive
|
|
16
|
-
setInterval(() => { }, 1000 * 60 * 60); // Heartbeat every hour
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
// Running in MCP mode (stdio)
|
|
20
|
-
await server.start();
|
|
21
|
-
}
|
|
5
|
+
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : undefined;
|
|
6
|
+
await server.start(port ? { httpPort: port } : undefined);
|
|
22
7
|
}
|
|
23
8
|
main().catch((error) => {
|
|
24
9
|
// Log errors to stderr and exit
|
package/dist/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseAccessServer } from "@access-mcp/shared";
|
|
2
2
|
export declare class AnnouncementsServer extends BaseAccessServer {
|
|
3
3
|
constructor();
|
|
4
|
-
protected getTools():
|
|
4
|
+
protected getTools(): {
|
|
5
5
|
name: string;
|
|
6
6
|
description: string;
|
|
7
7
|
inputSchema: {
|
|
@@ -10,12 +10,10 @@ export declare class AnnouncementsServer extends BaseAccessServer {
|
|
|
10
10
|
tags: {
|
|
11
11
|
type: string;
|
|
12
12
|
description: string;
|
|
13
|
-
required?: undefined;
|
|
14
13
|
};
|
|
15
14
|
ag: {
|
|
16
15
|
type: string;
|
|
17
16
|
description: string;
|
|
18
|
-
required?: undefined;
|
|
19
17
|
};
|
|
20
18
|
affiliation: {
|
|
21
19
|
type: string;
|
|
@@ -32,99 +30,46 @@ export declare class AnnouncementsServer extends BaseAccessServer {
|
|
|
32
30
|
start_date: {
|
|
33
31
|
type: string;
|
|
34
32
|
description: string;
|
|
33
|
+
format: string;
|
|
35
34
|
};
|
|
36
35
|
end_date: {
|
|
37
36
|
type: string;
|
|
38
37
|
description: string;
|
|
38
|
+
format: string;
|
|
39
39
|
};
|
|
40
40
|
limit: {
|
|
41
41
|
type: string;
|
|
42
42
|
description: string;
|
|
43
43
|
default: number;
|
|
44
44
|
};
|
|
45
|
-
period?: undefined;
|
|
46
45
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
properties: {
|
|
55
|
-
tags: {
|
|
56
|
-
type: string;
|
|
57
|
-
description: string;
|
|
58
|
-
required: boolean;
|
|
46
|
+
examples: ({
|
|
47
|
+
name: string;
|
|
48
|
+
arguments: {
|
|
49
|
+
relative_start_date: string;
|
|
50
|
+
limit: number;
|
|
51
|
+
tags?: undefined;
|
|
52
|
+
ag?: undefined;
|
|
59
53
|
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
} | {
|
|
55
|
+
name: string;
|
|
56
|
+
arguments: {
|
|
57
|
+
tags: string;
|
|
58
|
+
relative_start_date: string;
|
|
59
|
+
limit: number;
|
|
60
|
+
ag?: undefined;
|
|
64
61
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
required: string[];
|
|
74
|
-
};
|
|
75
|
-
} | {
|
|
76
|
-
name: string;
|
|
77
|
-
description: string;
|
|
78
|
-
inputSchema: {
|
|
79
|
-
type: string;
|
|
80
|
-
properties: {
|
|
81
|
-
ag: {
|
|
82
|
-
type: string;
|
|
83
|
-
description: string;
|
|
84
|
-
required: boolean;
|
|
62
|
+
} | {
|
|
63
|
+
name: string;
|
|
64
|
+
arguments: {
|
|
65
|
+
ag: string;
|
|
66
|
+
relative_start_date: string;
|
|
67
|
+
limit: number;
|
|
68
|
+
tags?: undefined;
|
|
85
69
|
};
|
|
86
|
-
|
|
87
|
-
type: string;
|
|
88
|
-
description: string;
|
|
89
|
-
default: number;
|
|
90
|
-
};
|
|
91
|
-
tags?: undefined;
|
|
92
|
-
affiliation?: undefined;
|
|
93
|
-
relative_start_date?: undefined;
|
|
94
|
-
relative_end_date?: undefined;
|
|
95
|
-
start_date?: undefined;
|
|
96
|
-
end_date?: undefined;
|
|
97
|
-
period?: undefined;
|
|
98
|
-
};
|
|
99
|
-
required: string[];
|
|
100
|
-
};
|
|
101
|
-
} | {
|
|
102
|
-
name: string;
|
|
103
|
-
description: string;
|
|
104
|
-
inputSchema: {
|
|
105
|
-
type: string;
|
|
106
|
-
properties: {
|
|
107
|
-
period: {
|
|
108
|
-
type: string;
|
|
109
|
-
description: string;
|
|
110
|
-
default: string;
|
|
111
|
-
};
|
|
112
|
-
limit: {
|
|
113
|
-
type: string;
|
|
114
|
-
description: string;
|
|
115
|
-
default: number;
|
|
116
|
-
};
|
|
117
|
-
tags?: undefined;
|
|
118
|
-
ag?: undefined;
|
|
119
|
-
affiliation?: undefined;
|
|
120
|
-
relative_start_date?: undefined;
|
|
121
|
-
relative_end_date?: undefined;
|
|
122
|
-
start_date?: undefined;
|
|
123
|
-
end_date?: undefined;
|
|
124
|
-
};
|
|
125
|
-
required?: undefined;
|
|
70
|
+
})[];
|
|
126
71
|
};
|
|
127
|
-
}
|
|
72
|
+
}[];
|
|
128
73
|
protected getResources(): {
|
|
129
74
|
uri: string;
|
|
130
75
|
name: string;
|
|
@@ -144,13 +89,11 @@ export declare class AnnouncementsServer extends BaseAccessServer {
|
|
|
144
89
|
text: string;
|
|
145
90
|
}[];
|
|
146
91
|
}>;
|
|
92
|
+
private normalizeLimit;
|
|
147
93
|
private buildAnnouncementsUrl;
|
|
148
94
|
private fetchAnnouncements;
|
|
149
95
|
private enhanceAnnouncements;
|
|
150
|
-
private
|
|
151
|
-
private getAnnouncementsByTags;
|
|
152
|
-
private getAnnouncementsByAffinityGroup;
|
|
153
|
-
private getRecentAnnouncements;
|
|
96
|
+
private searchAnnouncements;
|
|
154
97
|
private getPopularTags;
|
|
155
98
|
private getAffinityGroups;
|
|
156
99
|
}
|
package/dist/server.js
CHANGED
|
@@ -6,8 +6,8 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
6
6
|
getTools() {
|
|
7
7
|
return [
|
|
8
8
|
{
|
|
9
|
-
name: "
|
|
10
|
-
description: "Search ACCESS
|
|
9
|
+
name: "search_announcements",
|
|
10
|
+
description: "Search ACCESS announcements - general news, updates, and notifications from the community. Use this for news ABOUT things (e.g., 'registration deadline approaching', 'new feature released', 'policy change'). For actual training/workshop schedules and details, use search_events. For current system outages/maintenance, use infrastructure status tools. Note: Use relative_start_date='-1 year' or similar for broader search if recent results are limited.",
|
|
11
11
|
inputSchema: {
|
|
12
12
|
type: "object",
|
|
13
13
|
properties: {
|
|
@@ -17,7 +17,7 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
17
17
|
},
|
|
18
18
|
ag: {
|
|
19
19
|
type: "string",
|
|
20
|
-
description: "Filter by system/community affinity group.
|
|
20
|
+
description: "Filter by system/community affinity group (exact name match). Working examples: 'Anvil', 'ACCESS Support', 'DARWIN', 'Stampede-3'. Note: Use exact display names as they appear in announcements"
|
|
21
21
|
},
|
|
22
22
|
affiliation: {
|
|
23
23
|
type: "string",
|
|
@@ -25,85 +25,61 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
25
25
|
},
|
|
26
26
|
relative_start_date: {
|
|
27
27
|
type: "string",
|
|
28
|
-
description: "Filter announcements from a relative date. Examples: 'today', '-1 week', '-1 month', '-3 months', '-1 year'. Use negative values for past dates"
|
|
28
|
+
description: "Filter announcements from a relative date. Examples: 'today', '-1 week', '-1 month', '-3 months', '-1 year'. Use negative values for past dates. Common: '-1 month' for recent announcements"
|
|
29
29
|
},
|
|
30
30
|
relative_end_date: {
|
|
31
31
|
type: "string",
|
|
32
|
-
description: "Filter announcements up to a relative date. Examples: 'now', 'today', '-1 week' (past), '+1 week' (future)"
|
|
32
|
+
description: "Filter announcements up to a relative date. Examples: 'now', 'today', '-1 week' (past), '+1 week' (future). Usually 'now' or omit for current time"
|
|
33
33
|
},
|
|
34
34
|
start_date: {
|
|
35
35
|
type: "string",
|
|
36
|
-
description: "Filter announcements from exact date onwards (YYYY-MM-DD). Use when users specify dates like 'since January 1st, 2024' or 'from March 15th'"
|
|
36
|
+
description: "Filter announcements from exact date onwards (YYYY-MM-DD). Use when users specify dates like 'since January 1st, 2024' or 'from March 15th'",
|
|
37
|
+
format: "date"
|
|
37
38
|
},
|
|
38
39
|
end_date: {
|
|
39
40
|
type: "string",
|
|
40
|
-
description: "Filter announcements up to exact date (YYYY-MM-DD). Use when users specify dates like 'until December 31st, 2024' or 'before April 1st'"
|
|
41
|
+
description: "Filter announcements up to exact date (YYYY-MM-DD). Use when users specify dates like 'until December 31st, 2024' or 'before April 1st'",
|
|
42
|
+
format: "date"
|
|
41
43
|
},
|
|
42
44
|
limit: {
|
|
43
45
|
type: "number",
|
|
44
|
-
description: "Maximum number of announcements to return.
|
|
45
|
-
default:
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: "get_announcements_by_tags",
|
|
52
|
-
description: "Find announcements about specific topics or systems. Use when users ask about particular subjects like 'GPU maintenance', 'machine learning resources', 'training workshops', or 'cloud computing updates'.",
|
|
53
|
-
inputSchema: {
|
|
54
|
-
type: "object",
|
|
55
|
-
properties: {
|
|
56
|
-
tags: {
|
|
57
|
-
type: "string",
|
|
58
|
-
description: "Specific topics to search for (comma-separated). Popular examples: 'gpu,nvidia', 'machine-learning,ai', 'training,professional-development', 'data-science,python', 'cloud-computing', 'allocations-proposal'",
|
|
59
|
-
required: true
|
|
60
|
-
},
|
|
61
|
-
limit: {
|
|
62
|
-
type: "number",
|
|
63
|
-
description: "Maximum number of announcements to return",
|
|
64
|
-
default: 10
|
|
46
|
+
description: "Maximum number of announcements to return. Requested limit will be rounded to nearest valid API page size (5, 10, 25, or 50). Use 5-10 for quick overviews, 25-50 for comprehensive searches.",
|
|
47
|
+
default: 25
|
|
65
48
|
}
|
|
66
49
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
type: "object",
|
|
75
|
-
properties: {
|
|
76
|
-
ag: {
|
|
77
|
-
type: "string",
|
|
78
|
-
description: "The system or community group name (not the technical API ID). Examples: 'DELTA', 'Anvil', 'Bridges-2', 'ACCESS Support', 'Open OnDemand', 'Pegasus', 'CSSN (Computational Science Support Network)'",
|
|
79
|
-
required: true
|
|
50
|
+
examples: [
|
|
51
|
+
{
|
|
52
|
+
name: "Recent announcements",
|
|
53
|
+
arguments: {
|
|
54
|
+
relative_start_date: "-1 month",
|
|
55
|
+
limit: 10
|
|
56
|
+
}
|
|
80
57
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: "get_recent_announcements",
|
|
92
|
-
description: "Get the latest ACCESS support announcements from a recent time period. Use this when users ask 'what's new?', 'recent updates', 'latest announcements', or want a general overview of current activity.",
|
|
93
|
-
inputSchema: {
|
|
94
|
-
type: "object",
|
|
95
|
-
properties: {
|
|
96
|
-
period: {
|
|
97
|
-
type: "string",
|
|
98
|
-
description: "How far back to look for announcements. Examples: '1 week', '2 weeks', '1 month', '3 months', '6 months'. Default is '1 month'",
|
|
99
|
-
default: "1 month"
|
|
58
|
+
{
|
|
59
|
+
name: "GPU-related announcements",
|
|
60
|
+
arguments: {
|
|
61
|
+
tags: "gpu,nvidia",
|
|
62
|
+
relative_start_date: "-1 year",
|
|
63
|
+
limit: 25
|
|
64
|
+
}
|
|
100
65
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
66
|
+
{
|
|
67
|
+
name: "Anvil system announcements",
|
|
68
|
+
arguments: {
|
|
69
|
+
ag: "Anvil",
|
|
70
|
+
relative_start_date: "-6 months",
|
|
71
|
+
limit: 15
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "Machine learning announcements",
|
|
76
|
+
arguments: {
|
|
77
|
+
tags: "machine-learning,ai",
|
|
78
|
+
relative_start_date: "-1 year",
|
|
79
|
+
limit: 20
|
|
80
|
+
}
|
|
105
81
|
}
|
|
106
|
-
|
|
82
|
+
]
|
|
107
83
|
}
|
|
108
84
|
}
|
|
109
85
|
];
|
|
@@ -122,14 +98,8 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
122
98
|
const { name, arguments: args } = request.params;
|
|
123
99
|
try {
|
|
124
100
|
switch (name) {
|
|
125
|
-
case "
|
|
126
|
-
return await this.
|
|
127
|
-
case "get_announcements_by_tags":
|
|
128
|
-
return await this.getAnnouncementsByTags(args.tags, args.limit);
|
|
129
|
-
case "get_announcements_by_affinity_group":
|
|
130
|
-
return await this.getAnnouncementsByAffinityGroup(args.ag, args.limit);
|
|
131
|
-
case "get_recent_announcements":
|
|
132
|
-
return await this.getRecentAnnouncements(args.period, args.limit);
|
|
101
|
+
case "search_announcements":
|
|
102
|
+
return await this.searchAnnouncements(args);
|
|
133
103
|
default:
|
|
134
104
|
throw new Error(`Unknown tool: ${name}`);
|
|
135
105
|
}
|
|
@@ -174,8 +144,24 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
174
144
|
}
|
|
175
145
|
throw new Error(`Unknown resource: ${uri}`);
|
|
176
146
|
}
|
|
147
|
+
normalizeLimit(limit) {
|
|
148
|
+
// Drupal API only accepts specific pagination values: 5, 10, 25, 50
|
|
149
|
+
const validSizes = [5, 10, 25, 50];
|
|
150
|
+
const requestedLimit = limit || 25; // Default to 25 (valid API value)
|
|
151
|
+
// Find the closest valid size
|
|
152
|
+
if (requestedLimit <= 5)
|
|
153
|
+
return 5;
|
|
154
|
+
if (requestedLimit <= 10)
|
|
155
|
+
return 10;
|
|
156
|
+
if (requestedLimit <= 25)
|
|
157
|
+
return 25;
|
|
158
|
+
return 50;
|
|
159
|
+
}
|
|
177
160
|
buildAnnouncementsUrl(filters) {
|
|
178
161
|
const params = new URLSearchParams();
|
|
162
|
+
// Add required pagination parameter for 2.2 API
|
|
163
|
+
// The Drupal API only accepts: 5, 10, 25, or 50
|
|
164
|
+
params.append("items_per_page", String(this.normalizeLimit(filters.limit)));
|
|
179
165
|
if (filters.tags) {
|
|
180
166
|
params.append("tags", filters.tags);
|
|
181
167
|
}
|
|
@@ -197,7 +183,7 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
197
183
|
if (filters.end_date) {
|
|
198
184
|
params.append("end_date", filters.end_date);
|
|
199
185
|
}
|
|
200
|
-
return `/api/2.
|
|
186
|
+
return `/api/2.2/announcements?${params.toString()}`;
|
|
201
187
|
}
|
|
202
188
|
async fetchAnnouncements(filters) {
|
|
203
189
|
const url = this.buildAnnouncementsUrl(filters);
|
|
@@ -211,26 +197,23 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
211
197
|
enhanceAnnouncements(rawAnnouncements) {
|
|
212
198
|
return rawAnnouncements.map(announcement => ({
|
|
213
199
|
...announcement,
|
|
214
|
-
date: announcement.
|
|
215
|
-
tags: announcement.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
formatted_date: announcement.field_published_date
|
|
219
|
-
? new Date(announcement.field_published_date).toLocaleDateString('en-US', {
|
|
200
|
+
date: announcement.published_date,
|
|
201
|
+
tags: Array.isArray(announcement.tags) ? announcement.tags : [],
|
|
202
|
+
formatted_date: announcement.published_date
|
|
203
|
+
? new Date(announcement.published_date).toLocaleDateString('en-US', {
|
|
220
204
|
year: 'numeric',
|
|
221
205
|
month: 'long',
|
|
222
206
|
day: 'numeric'
|
|
223
207
|
})
|
|
224
208
|
: '',
|
|
225
|
-
body_preview: announcement.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
: []
|
|
209
|
+
body_preview: announcement.summary ||
|
|
210
|
+
(announcement.body
|
|
211
|
+
? announcement.body.replace(/<[^>]*>/g, '').substring(0, 200) + '...'
|
|
212
|
+
: ''),
|
|
213
|
+
affinity_groups: Array.isArray(announcement.affinity_group) ? announcement.affinity_group : []
|
|
231
214
|
}));
|
|
232
215
|
}
|
|
233
|
-
async
|
|
216
|
+
async searchAnnouncements(filters) {
|
|
234
217
|
const announcements = await this.fetchAnnouncements(filters);
|
|
235
218
|
const limited = filters.limit ? announcements.slice(0, filters.limit) : announcements;
|
|
236
219
|
// Build filters_applied object
|
|
@@ -264,20 +247,6 @@ export class AnnouncementsServer extends BaseAccessServer {
|
|
|
264
247
|
]
|
|
265
248
|
};
|
|
266
249
|
}
|
|
267
|
-
async getAnnouncementsByTags(tags, limit = 10) {
|
|
268
|
-
return await this.getAnnouncements({ tags, limit });
|
|
269
|
-
}
|
|
270
|
-
async getAnnouncementsByAffinityGroup(ag, limit = 10) {
|
|
271
|
-
return await this.getAnnouncements({ ag, limit });
|
|
272
|
-
}
|
|
273
|
-
async getRecentAnnouncements(period = "1 month", limit = 10) {
|
|
274
|
-
const relativeStart = `-${period}`;
|
|
275
|
-
return await this.getAnnouncements({
|
|
276
|
-
relative_start_date: relativeStart,
|
|
277
|
-
relative_end_date: "now",
|
|
278
|
-
limit
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
250
|
getPopularTags(announcements) {
|
|
282
251
|
const tagCounts = {};
|
|
283
252
|
announcements.forEach(announcement => {
|